[vlc-devel] [PATCH 01/17] Split block_t to vlc_data_t and vlc_frame_t

Denis Charmet typx at dinauz.org
Mon Apr 22 19:10:30 CEST 2019


---
 extras/analyser/vlc.vim              |   3 +-
 include/vlc_aout.h                   |  12 +-
 include/vlc_aout_volume.h            |   2 +-
 include/vlc_block_helper.h           | 369 -----------------------
 include/vlc_boxes.h                  |  10 +-
 include/vlc_codec.h                  |  76 ++---
 include/vlc_common.h                 |   8 +-
 include/vlc_data.h                   | 392 ++++++++++++++++++++++++
 include/vlc_data_helper.h            | 369 +++++++++++++++++++++++
 include/vlc_demux.h                  |   4 +-
 include/vlc_es_out.h                 |   6 +-
 include/vlc_filter.h                 |   6 +-
 include/{vlc_block.h => vlc_frame.h} | 369 +++++++++++------------
 include/vlc_frame_helper.h           | 369 +++++++++++++++++++++++
 include/vlc_httpd.h                  |   2 +-
 include/vlc_image.h                  |   5 +-
 include/vlc_input.h                  |   2 +-
 include/vlc_picture.h                |   3 +-
 include/vlc_sout.h                   |  19 +-
 include/vlc_stream.h                 |  21 +-
 include/vlc_stream_extractor.h       |   8 +-
 include/vlc_threads.h                |   2 +-
 include/vlc_vout.h                   |   2 +-
 po/POTFILES.in                       |   9 +-
 src/Makefile.am                      |   8 +-
 src/audio_output/aout_internal.h     |   4 +-
 src/audio_output/dec.c               |  44 +--
 src/audio_output/filters.c           |  68 ++---
 src/audio_output/volume.c            |   4 +-
 src/check_symbols                    |   2 +-
 src/input/access.c                   |   4 +-
 src/input/decoder.c                  | 198 ++++++-------
 src/input/demux_chained.c            |   5 +-
 src/input/es_out.c                   |  34 +--
 src/input/es_out_timeshift.c         |  74 ++---
 src/input/stream.c                   | 118 ++++----
 src/input/stream_extractor.c         |   2 +-
 src/input/stream_fifo.c              | 115 ++++----
 src/libvlccore.sym                   |  59 ++--
 src/misc/data.c                      | 426 +++++++++++++++++++++++++++
 src/misc/fifo.c                      | 258 +++++++++++++---
 src/misc/{block.c => frame.c}        | 246 ++++++++--------
 src/misc/image.c                     |  50 ++--
 src/misc/picture.c                   |  13 +-
 src/missing.c                        |  12 +-
 src/modules/bank.c                   |   8 +-
 src/modules/cache.c                  |  34 +--
 src/modules/modules.h                |   2 +-
 src/network/httpd.c                  |  14 +-
 src/stream_output/stream_output.c    |  34 +--
 src/stream_output/stream_output.h    |   2 +-
 src/test/block_test.c                | 125 +++++---
 src/video_output/display.c           |   1 -
 src/video_output/snapshot.c          |   4 +-
 src/video_output/snapshot.h          |   2 +-
 src/video_output/video_output.c      |   2 +-
 src/video_output/vout_intf.c         |   6 +-
 test/modules/packetizer/helpers.c    |   4 +-
 test/modules/packetizer/hxxx.c       |   6 +-
 test/src/input/decoder.c             |  26 +-
 test/src/input/decoder.h             |   2 +-
 test/src/input/demux-run.c           |   4 +-
 test/src/input/stream_fifo.c         |  20 +-
 63 files changed, 2780 insertions(+), 1328 deletions(-)
 delete mode 100644 include/vlc_block_helper.h
 create mode 100644 include/vlc_data.h
 create mode 100644 include/vlc_data_helper.h
 rename include/{vlc_block.h => vlc_frame.h} (54%)
 create mode 100644 include/vlc_frame_helper.h
 create mode 100644 src/misc/data.c
 rename src/misc/{block.c => frame.c} (55%)

diff --git a/extras/analyser/vlc.vim b/extras/analyser/vlc.vim
index 8618f82580..57c8be6d07 100644
--- a/extras/analyser/vlc.vim
+++ b/extras/analyser/vlc.vim
@@ -79,7 +79,8 @@ function VlcSyntax()
   " Filters
   syn keyword cType filter_t filter_sys_t
   " Blocks
-  syn keyword cType block_t block_fifo_t
+  syn keyword cType vlc_frame_t vlc_frame_fifo_t
+  syn keyword cType vlc_data_t vlc_data_fifo_t
   " Network
   syn keyword cType network_socket_t vlc_acl_t 
   " HTTPD
diff --git a/include/vlc_aout.h b/include/vlc_aout.h
index 43fbf2f120..ec34025153 100644
--- a/include/vlc_aout.h
+++ b/include/vlc_aout.h
@@ -109,7 +109,7 @@
 #define A52_FRAME_NB 1536
 
 /* FIXME to remove once aout.h is cleaned a bit more */
-#include <vlc_block.h>
+#include <vlc_frame.h>
 
 struct vlc_audio_output_events {
     void (*timing_report)(audio_output_t *, vlc_tick_t system_now, vlc_tick_t pts);
@@ -186,10 +186,10 @@ struct audio_output
       * \note This callback cannot be called in stopped state.
       */
 
-    void (*play)(audio_output_t *, block_t *block, vlc_tick_t date);
-    /**< Queues a block of samples for playback (mandatory, cannot be NULL).
+    void (*play)(audio_output_t *, vlc_frame_t *frame, vlc_tick_t date);
+    /**< Queues a frame of samples for playback (mandatory, cannot be NULL).
       *
-      * \param block block of audio samples
+      * \param frame frame of audio samples
       * \param date intended system time to render the first sample
       *
       * \note This callback cannot be called in stopped state.
@@ -509,8 +509,8 @@ VLC_API void aout_FiltersDelete(vlc_object_t *, aout_filters_t *);
 #define aout_FiltersDelete(o,f) \
         aout_FiltersDelete(VLC_OBJECT(o),f)
 VLC_API bool aout_FiltersAdjustResampling(aout_filters_t *, int);
-VLC_API block_t *aout_FiltersPlay(aout_filters_t *, block_t *, float rate);
-VLC_API block_t *aout_FiltersDrain(aout_filters_t *);
+VLC_API vlc_frame_t *aout_FiltersPlay(aout_filters_t *, vlc_frame_t *, float rate);
+VLC_API vlc_frame_t *aout_FiltersDrain(aout_filters_t *);
 VLC_API void     aout_FiltersFlush(aout_filters_t *);
 VLC_API void     aout_FiltersChangeViewpoint(aout_filters_t *, const vlc_viewpoint_t *vp);
 
diff --git a/include/vlc_aout_volume.h b/include/vlc_aout_volume.h
index 4988ef1014..5965cb0fe2 100644
--- a/include/vlc_aout_volume.h
+++ b/include/vlc_aout_volume.h
@@ -46,7 +46,7 @@ struct audio_volume
     struct vlc_object_t obj;
 
     vlc_fourcc_t format; /**< Audio samples format */
-    void (*amplify)(audio_volume_t *, block_t *, float); /**< Amplifier */
+    void (*amplify)(audio_volume_t *, vlc_frame_t *, float); /**< Amplifier */
 };
 
 /** @} */
diff --git a/include/vlc_block_helper.h b/include/vlc_block_helper.h
deleted file mode 100644
index 4071c2b54d..0000000000
--- a/include/vlc_block_helper.h
+++ /dev/null
@@ -1,369 +0,0 @@
-/*****************************************************************************
- * vlc_block_helper.h: Helper functions for data blocks management.
- *****************************************************************************
- * Copyright (C) 2003-2017 VLC authors and VideoLAN
- *
- * Authors: Gildas Bazin <gbazin at netcourrier.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-#ifndef VLC_BLOCK_HELPER_H
-#define VLC_BLOCK_HELPER_H 1
-
-#include <vlc_block.h>
-
-typedef struct block_bytestream_t
-{
-    block_t *p_chain;  /**< byte stream head block */
-    block_t **pp_last; /**< tail ppointer for appends */
-    block_t *p_block;  /**< byte stream read pointer block */
-    size_t   i_block_offset; /**< byte stream read pointer offset within block */
-    size_t   i_base_offset; /**< block base offset (previous blocks total size) */
-    size_t   i_total;  /**< total bytes over all linked blocks */
-} block_bytestream_t;
-
-/*****************************************************************************
- * block_bytestream_t management
- *****************************************************************************/
-static inline void block_BytestreamInit( block_bytestream_t *p_bytestream )
-{
-    p_bytestream->p_chain = p_bytestream->p_block = NULL;
-    p_bytestream->pp_last = &p_bytestream->p_chain;
-    p_bytestream->i_block_offset = 0;
-    p_bytestream->i_base_offset = 0;
-    p_bytestream->i_total = 0;
-}
-
-static inline void block_BytestreamRelease( block_bytestream_t *p_bytestream )
-{
-    block_ChainRelease( p_bytestream->p_chain );
-}
-
-/**
- * It flush all data (read and unread) from a block_bytestream_t.
- */
-static inline void block_BytestreamEmpty( block_bytestream_t *p_bytestream )
-{
-    block_BytestreamRelease( p_bytestream );
-    block_BytestreamInit( p_bytestream );
-}
-
-/**
- * It flushes all already read data from a block_bytestream_t.
- */
-static inline void block_BytestreamFlush( block_bytestream_t *p_bytestream )
-{
-    block_t *block = p_bytestream->p_chain;
-
-    while( block != p_bytestream->p_block )
-    {
-        block_t *p_next = block->p_next;
-
-        p_bytestream->i_total -= block->i_buffer;
-        p_bytestream->i_base_offset -= block->i_buffer;
-        block_Release( block );
-        block = p_next;
-    }
-
-    while( block != NULL && block->i_buffer == p_bytestream->i_block_offset )
-    {
-        block_t *p_next = block->p_next;
-
-        p_bytestream->i_total -= block->i_buffer;
-        block_Release( block );
-        block = p_next;
-        p_bytestream->i_block_offset = 0;
-    }
-
-    p_bytestream->p_chain = p_bytestream->p_block = block;
-    if( p_bytestream->p_chain == NULL )
-        p_bytestream->pp_last = &p_bytestream->p_chain;
-}
-
-static inline void block_BytestreamPush( block_bytestream_t *p_bytestream,
-                                         block_t *p_block )
-{
-    block_ChainLastAppend( &p_bytestream->pp_last, p_block );
-    if( !p_bytestream->p_block ) p_bytestream->p_block = p_block;
-    for( ; p_block; p_block = p_block->p_next )
-        p_bytestream->i_total += p_block->i_buffer;
-}
-
-static inline size_t block_BytestreamRemaining( const block_bytestream_t *p_bytestream )
-{
-    return ( p_bytestream->i_total > p_bytestream->i_base_offset + p_bytestream->i_block_offset ) ?
-             p_bytestream->i_total - p_bytestream->i_base_offset - p_bytestream->i_block_offset : 0;
-}
-
-VLC_USED
-static inline block_t *block_BytestreamPop( block_bytestream_t *p_bytestream )
-{
-    block_t *p_block;
-
-    block_BytestreamFlush( p_bytestream );
-
-    p_block = p_bytestream->p_block;
-    if( unlikely( p_block == NULL ) )
-    {
-        return NULL;
-    }
-    else if( !p_block->p_next )
-    {
-        p_block->p_buffer += p_bytestream->i_block_offset;
-        p_block->i_buffer -= p_bytestream->i_block_offset;
-        p_bytestream->i_block_offset = 0;
-        p_bytestream->i_total = 0;
-        p_bytestream->p_chain = p_bytestream->p_block = NULL;
-        p_bytestream->pp_last = &p_bytestream->p_chain;
-        return p_block;
-    }
-
-    while( p_block->p_next && p_block->p_next->p_next )
-        p_block = p_block->p_next;
-
-    block_t *p_block_old = p_block;
-    p_block = p_block->p_next;
-    p_block_old->p_next = NULL;
-    p_bytestream->pp_last = &p_block_old->p_next;
-    if( p_block )
-        p_bytestream->i_total -= p_block->i_buffer;
-
-    return p_block;
-}
-
-static inline int block_WaitBytes( block_bytestream_t *p_bytestream,
-                                   size_t i_data )
-{
-    if( block_BytestreamRemaining( p_bytestream ) >= i_data )
-        return VLC_SUCCESS;
-    return VLC_EGENERIC;
-}
-
-static inline int block_PeekBytes( block_bytestream_t *p_bytestream,
-                                   uint8_t *p_data, size_t i_data )
-{
-    if( block_BytestreamRemaining( p_bytestream ) < i_data )
-        return VLC_EGENERIC;
-
-    /* Copy the data */
-    size_t i_offset = p_bytestream->i_block_offset;
-    size_t i_size = i_data;
-    for( block_t *p_block = p_bytestream->p_block;
-         p_block != NULL; p_block = p_block->p_next )
-    {
-        size_t i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
-        i_size -= i_copy;
-
-        if( i_copy )
-        {
-            memcpy( p_data, p_block->p_buffer + i_offset, i_copy );
-            p_data += i_copy;
-        }
-
-        i_offset = 0;
-
-        if( !i_size ) break;
-    }
-
-    return VLC_SUCCESS;
-}
-
-static inline int block_GetBytes( block_bytestream_t *p_bytestream,
-                                  uint8_t *p_data, size_t i_data )
-{
-    if( block_BytestreamRemaining( p_bytestream ) < i_data )
-        return VLC_EGENERIC;
-
-    /* Copy the data */
-    size_t i_offset = p_bytestream->i_block_offset;
-    size_t i_size = i_data;
-    size_t i_copy = 0;
-    block_t *p_block;
-    for( p_block = p_bytestream->p_block;
-         p_block != NULL; p_block = p_block->p_next )
-    {
-        i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
-        i_size -= i_copy;
-
-        if( i_copy && p_data != NULL )
-        {
-            memcpy( p_data, p_block->p_buffer + i_offset, i_copy );
-            p_data += i_copy;
-        }
-
-        if( i_size == 0 )
-            break;
-
-        p_bytestream->i_base_offset += p_block->i_buffer;
-        i_offset = 0;
-    }
-
-    p_bytestream->p_block = p_block;
-    p_bytestream->i_block_offset = i_offset + i_copy;
-
-    return VLC_SUCCESS;
-}
-
-static inline int block_SkipBytes( block_bytestream_t *p_bytestream,
-                                   size_t i_data )
-{
-    return block_GetBytes( p_bytestream, NULL, i_data );
-}
-
-static inline int block_SkipByte( block_bytestream_t *p_bytestream )
-{
-    return block_GetBytes( p_bytestream, NULL, 1 );
-}
-
-static inline int block_PeekOffsetBytes( block_bytestream_t *p_bytestream,
-    size_t i_peek_offset, uint8_t *p_data, size_t i_data )
-{
-    const size_t i_remain = block_BytestreamRemaining( p_bytestream );
-    if( i_remain < i_data + i_peek_offset )
-        return VLC_EGENERIC;
-
-    /* Find the right place */
-    size_t i_offset = p_bytestream->i_block_offset;
-    size_t i_size = i_peek_offset;
-    size_t i_copy = 0;
-    block_t *p_block;
-    for( p_block = p_bytestream->p_block;
-         p_block != NULL; p_block = p_block->p_next )
-    {
-        i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
-        i_size -= i_copy;
-
-        if( !i_size ) break;
-
-        i_offset = 0;
-    }
-
-    /* Copy the data */
-    i_offset += i_copy;
-    i_size = i_data;
-    for( ; p_block != NULL; p_block = p_block->p_next )
-    {
-        i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
-        i_size -= i_copy;
-
-        if( i_copy )
-        {
-            memcpy( p_data, p_block->p_buffer + i_offset, i_copy );
-            p_data += i_copy;
-        }
-
-        i_offset = 0;
-
-        if( !i_size ) break;
-    }
-
-    return VLC_SUCCESS;
-}
-
-typedef const uint8_t * (*block_startcode_helper_t)( const uint8_t *, const uint8_t * );
-typedef bool (*block_startcode_matcher_t)( uint8_t, size_t, const uint8_t * );
-
-static inline int block_FindStartcodeFromOffset(
-    block_bytestream_t *p_bytestream, size_t *pi_offset,
-    const uint8_t *p_startcode, int i_startcode_length,
-    block_startcode_helper_t p_startcode_helper,
-    block_startcode_matcher_t p_startcode_matcher )
-{
-    block_t *p_block, *p_block_backup = 0;
-    ssize_t i_size = 0;
-    size_t i_offset, i_offset_backup = 0;
-    int i_caller_offset_backup = 0, i_match;
-
-    /* Find the right place */
-    i_size = *pi_offset + p_bytestream->i_block_offset;
-    for( p_block = p_bytestream->p_block;
-         p_block != NULL; p_block = p_block->p_next )
-    {
-        i_size -= p_block->i_buffer;
-        if( i_size < 0 ) break;
-    }
-
-    if( unlikely( i_size >= 0 ) )
-    {
-        /* Not enough data, bail out */
-        return VLC_EGENERIC;
-    }
-
-    /* Begin the search.
-     * We first look for an occurrence of the 1st startcode byte and
-     * if found, we do a more thorough check. */
-    i_size += p_block->i_buffer;
-    *pi_offset -= i_size;
-    i_match = 0;
-    for( ; p_block != NULL; p_block = p_block->p_next )
-    {
-        for( i_offset = i_size; i_offset < p_block->i_buffer; i_offset++ )
-        {
-            /* Use optimized helper when possible */
-            if( p_startcode_helper && !i_match &&
-               (p_block->i_buffer - i_offset) > ((size_t)i_startcode_length - 1) )
-            {
-                const uint8_t *p_res = p_startcode_helper( &p_block->p_buffer[i_offset],
-                                                           &p_block->p_buffer[p_block->i_buffer] );
-                if( p_res )
-                {
-                    *pi_offset += i_offset + (p_res - &p_block->p_buffer[i_offset]);
-                    return VLC_SUCCESS;
-                }
-                /* Then parsing boundary with legacy code */
-                i_offset = p_block->i_buffer - (i_startcode_length - 1);
-            }
-
-            bool b_matched = ( p_startcode_matcher )
-                           ? p_startcode_matcher( p_block->p_buffer[i_offset], i_match, p_startcode )
-                           : p_block->p_buffer[i_offset] == p_startcode[i_match];
-            if( b_matched )
-            {
-                if( i_match == 0 )
-                {
-                    p_block_backup = p_block;
-                    i_offset_backup = i_offset;
-                    i_caller_offset_backup = *pi_offset;
-                }
-
-                if( i_match + 1 == i_startcode_length )
-                {
-                    /* We have it */
-                    *pi_offset += i_offset - i_match;
-                    return VLC_SUCCESS;
-                }
-
-                i_match++;
-            }
-            else if ( i_match > 0 )
-            {
-                /* False positive */
-                p_block = p_block_backup;
-                i_offset = i_offset_backup;
-                *pi_offset = i_caller_offset_backup;
-                i_match = 0;
-            }
-
-        }
-        i_size = 0;
-        *pi_offset += i_offset;
-    }
-
-    *pi_offset -= i_match;
-    return VLC_EGENERIC;
-}
-
-#endif /* VLC_BLOCK_HELPER_H */
diff --git a/include/vlc_boxes.h b/include/vlc_boxes.h
index 69c26c027f..39cb786f10 100644
--- a/include/vlc_boxes.h
+++ b/include/vlc_boxes.h
@@ -25,7 +25,7 @@
 #define VLC_BOXES_H
 
 #include <vlc_common.h>
-#include <vlc_block.h>
+#include <vlc_frame.h>
 
 /**
  * \file
@@ -34,13 +34,13 @@
 
 typedef struct bo_t
 {
-    block_t     *b;
+    vlc_frame_t     *b;
     size_t      basesize;
 } bo_t;
 
 static inline bool bo_init(bo_t *p_bo, int i_size)
 {
-    p_bo->b = block_Alloc(i_size);
+    p_bo->b = vlc_frame_Alloc(i_size);
     if (p_bo->b == NULL)
         return false;
 
@@ -53,7 +53,7 @@ static inline bool bo_init(bo_t *p_bo, int i_size)
 static inline void bo_deinit(bo_t *p_bo)
 {
     if(p_bo->b)
-        block_Release(p_bo->b);
+        vlc_frame_Release(p_bo->b);
 }
 
 static inline void bo_free(bo_t *p_bo)
@@ -76,7 +76,7 @@ static inline int bo_extend(bo_t *p_bo, size_t i_total)
             i_growth += p_bo->basesize;
 
         int i = p_bo->b->i_buffer; /* Realloc would set payload size == buffer size */
-        p_bo->b = block_Realloc(p_bo->b, 0, i_size + i_growth);
+        p_bo->b = vlc_frame_Realloc(p_bo->b, 0, i_size + i_growth);
         if (!p_bo->b)
             return false;
         p_bo->b->i_buffer = i;
diff --git a/include/vlc_codec.h b/include/vlc_codec.h
index 71f3e8439f..2b4ff14a5c 100644
--- a/include/vlc_codec.h
+++ b/include/vlc_codec.h
@@ -25,7 +25,7 @@
 
 #include <assert.h>
 
-#include <vlc_block.h>
+#include <vlc_frame.h>
 #include <vlc_es.h>
 #include <vlc_vout_window.h>
 #include <vlc_picture.h>
@@ -56,7 +56,7 @@ struct decoder_owner_callbacks
             /* cf.decoder_QueueVideo */
             void        (*queue)( decoder_t *, picture_t * );
             /* cf.decoder_QueueCC */
-            void        (*queue_cc)( decoder_t *, block_t *,
+            void        (*queue_cc)( decoder_t *, vlc_frame_t *,
                                      const decoder_cc_desc_t * );
 
             /* Display date
@@ -71,7 +71,7 @@ struct decoder_owner_callbacks
             int     (*format_update)( decoder_t * );
 
             /* cf.decoder_QueueAudio */
-            void    (*queue)( decoder_t *, block_t * );
+            void    (*queue)( decoder_t *, vlc_frame_t * );
         } audio;
         struct
         {
@@ -124,15 +124,15 @@ struct decoder_t
 #       define VLCDEC_SUCCESS   VLC_SUCCESS
 #       define VLCDEC_ECRITICAL VLC_EGENERIC
 #       define VLCDEC_RELOAD    (-100)
-        /* This function is called to decode one packetized block.
+        /* This function is called to decode one packetized frame.
          *
-         * The module implementation will own the input block (p_block) and should
+         * The module implementation will own the input frame (p_frame) and should
          * process and release it. Depending of the decoder type, the module should
-         * send output frames/blocks via decoder_QueueVideo(), decoder_QueueAudio()
+         * send output frames/frames via decoder_QueueVideo(), decoder_QueueAudio()
          * or decoder_QueueSub().
          *
-         * If p_block is NULL, the decoder asks the module to drain itself. The
-         * module should return all available output frames/block via the queue
+         * If p_frame is NULL, the decoder asks the module to drain itself. The
+         * module should return all available output frames/frame via the queue
          * functions.
          *
          * Return values can be:
@@ -142,39 +142,39 @@ struct decoder_t
          *  VLCDEC_RELOAD: Request that the decoder should be reloaded. The current
          *  module will be unloaded. Reloading a module may cause a loss of frames.
          *  When returning this status, the implementation shouldn't release or
-         *  modify the p_block in argument (The same p_block will be feed to the
+         *  modify the p_frame in argument (The same p_frame will be feed to the
          *  next decoder module).
          */
-        int             ( * pf_decode )   ( decoder_t *, block_t *p_block );
+        int             ( * pf_decode )   ( decoder_t *, vlc_frame_t *p_frame );
 
-        /* This function is called in a loop with the same pp_block argument until
+        /* This function is called in a loop with the same pp_frame argument until
          * it returns NULL. This allows a module implementation to return more than
-         * one output blocks for one input block.
+         * one output frames for one input frame.
          *
-         * pp_block or *pp_block can be NULL.
+         * pp_frame or *pp_frame can be NULL.
          *
-         * If pp_block and *pp_block are not NULL, the module implementation will
-         * own the input block (*pp_block) and should process and release it. The
-         * module can also process a part of the block. In that case, it should
-         * modify (*pp_block)->p_buffer/i_buffer accordingly and return a valid
-         * output block. The module can also set *pp_block to NULL when the input
-         * block is consumed.
+         * If pp_frame and *pp_frame are not NULL, the module implementation will
+         * own the input frame (*pp_frame) and should process and release it. The
+         * module can also process a part of the frame. In that case, it should
+         * modify (*pp_frame)->p_buffer/i_buffer accordingly and return a valid
+         * output frame. The module can also set *pp_frame to NULL when the input
+         * frame is consumed.
          *
-         * If pp_block is not NULL but *pp_block is NULL, a previous call of the pf
-         * function has set the *pp_block to NULL. Here, the module can return new
-         * output block for the same, already processed, input block (the
+         * If pp_frame is not NULL but *pp_frame is NULL, a previous call of the pf
+         * function has set the *pp_frame to NULL. Here, the module can return new
+         * output frame for the same, already processed, input frame (the
          * pf_packetize function will be called as long as the module return an
-         * output block).
+         * output frame).
          *
          * When the pf function returns NULL, the next call to this function will
-         * have a new a valid pp_block (if the packetizer is not drained).
+         * have a new a valid pp_frame (if the packetizer is not drained).
          *
-         * If pp_block is NULL, the packetizer asks the module to drain itself. In
+         * If pp_frame is NULL, the packetizer asks the module to drain itself. In
          * that case, the module has to return all output frames available (the
          * pf_packetize function will be called as long as the module return an
-         * output block).
+         * output frame).
          */
-        block_t *       ( * pf_packetize )( decoder_t *, block_t **pp_block );
+        vlc_frame_t *       ( * pf_packetize )( decoder_t *, vlc_frame_t **pp_frame );
     };
 
     /* */
@@ -186,7 +186,7 @@ struct decoder_t
      * channel bitmaps will be used to known which cc channel are present (but
      * globaly, not necessary for the current packet. Video decoders should use
      * the decoder_QueueCc() function to pass closed captions. */
-    block_t *           ( * pf_get_cc )      ( decoder_t *, decoder_cc_desc_t * );
+    vlc_frame_t *           ( * pf_get_cc )      ( decoder_t *, decoder_cc_desc_t * );
 
     /* Meta data at codec level
      *  The decoder owner set it back to NULL once it has retreived what it needs.
@@ -232,9 +232,9 @@ struct encoder_t
     /* Properties of the output of the encoder */
     es_format_t         fmt_out;
 
-    block_t *           ( * pf_encode_video )( encoder_t *, picture_t * );
-    block_t *           ( * pf_encode_audio )( encoder_t *, block_t * );
-    block_t *           ( * pf_encode_sub )( encoder_t *, subpicture_t * );
+    vlc_frame_t *           ( * pf_encode_video )( encoder_t *, picture_t * );
+    vlc_frame_t *           ( * pf_encode_audio )( encoder_t *, vlc_frame_t * );
+    vlc_frame_t *           ( * pf_encode_sub )( encoder_t *, subpicture_t * );
 
     /* Common encoder options */
     int i_threads;               /* Number of threads to use during encoding */
@@ -343,25 +343,25 @@ static inline void decoder_QueueVideo( decoder_t *dec, picture_t *p_pic )
  * \param p_cc the closed-caption to queue
  * \param p_desc decoder_cc_desc_t description structure
  */
-static inline void decoder_QueueCc( decoder_t *dec, block_t *p_cc,
+static inline void decoder_QueueCc( decoder_t *dec, vlc_frame_t *p_cc,
                                    const decoder_cc_desc_t *p_desc )
 {
     vlc_assert( dec->fmt_in.i_cat == VIDEO_ES && dec->cbs != NULL );
 
     if( dec->cbs->video.queue_cc == NULL )
-        block_Release( p_cc );
+        vlc_frame_Release( p_cc );
     else
         dec->cbs->video.queue_cc( dec, p_cc, p_desc );
 }
 
 /**
- * This function queues a single audio block to the audio output.
+ * This function queues a single audio frame to the audio output.
  *
  * \note
- * The caller doesn't own the audio block anymore after this call (even in case
+ * The caller doesn't own the audio frame anymore after this call (even in case
  * of error).
  */
-static inline void decoder_QueueAudio( decoder_t *dec, block_t *p_aout_buf )
+static inline void decoder_QueueAudio( decoder_t *dec, vlc_frame_t *p_aout_buf )
 {
     vlc_assert( dec->fmt_in.i_cat == AUDIO_ES && dec->cbs != NULL );
     vlc_assert( p_aout_buf->p_next == NULL );
@@ -402,10 +402,10 @@ static inline int decoder_UpdateAudioFormat( decoder_t *dec )
 
 /**
  * This function will return a new audio buffer usable by a decoder as an
- * output buffer. It must be released with block_Release() or returned it to
+ * output buffer. It must be released with vlc_frame_Release() or returned it to
  * the caller as a decoder_QueueAudio parameter.
  */
-VLC_API block_t * decoder_NewAudioBuffer( decoder_t *, int i_nb_samples ) VLC_USED;
+VLC_API vlc_frame_t * decoder_NewAudioBuffer( decoder_t *, int i_nb_samples ) VLC_USED;
 
 /**
  * This function will return a new subpicture usable by a decoder as an output
diff --git a/include/vlc_common.h b/include/vlc_common.h
index c2e14e4209..c24dc9fb33 100644
--- a/include/vlc_common.h
+++ b/include/vlc_common.h
@@ -423,9 +423,11 @@ typedef struct vlc_url_t vlc_url_t;
 /* Misc */
 typedef struct iso639_lang_t iso639_lang_t;
 
-/* block */
-typedef struct block_t      block_t;
-typedef struct block_fifo_t block_fifo_t;
+/* Frames */
+typedef struct vlc_frame_t      vlc_frame_t;
+
+/* Data Blocks */
+typedef struct vlc_data_t      vlc_data_t;
 
 /* Hashing */
 typedef struct md5_s md5_t;
diff --git a/include/vlc_data.h b/include/vlc_data.h
new file mode 100644
index 0000000000..202c117b71
--- /dev/null
+++ b/include/vlc_data.h
@@ -0,0 +1,392 @@
+/*****************************************************************************
+ * vlc_data.h: Data blocks management functions
+ *****************************************************************************
+ * Copyright (C) 2003 VLC authors and VideoLAN
+ * $Id: 62756edf3e644fafa5384c15eadb6d317c55188b $
+ *
+ * Authors: Laurent Aimar <fenrir at via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VLC_DATA_H
+#define VLC_DATA_H 1
+
+/**
+ * \defgroup data Data blocks
+ * \ingroup input
+ *
+ * Generic data block handlers mostly used between accesses and demuxes
+ *
+ * @{
+ * \file
+ * Data datablock definition and functions
+ */
+
+#include <sys/types.h>  /* for ssize_t */
+
+/****************************************************************************
+ * data:
+ ****************************************************************************
+ * - i_buffer number of valid data pointed by p_buffer
+ *      you can freely decrease it but never increase it yourself
+ *      (use vlc_data_Realloc)
+ * - p_buffer: pointer over datas. You should never overwrite it, you can
+ *   only incremment it to skip datas, in others cases use vlc_data_Realloc
+ *   (don't duplicate yourself in a bigger buffer, vlc_data_Realloc is
+ *   optimised for preheader/postdatas increase)
+ ****************************************************************************/
+
+struct vlc_data_callbacks
+{
+    void (*free)(vlc_data_t *);
+};
+
+struct vlc_data_t
+{
+    vlc_data_t    *p_next;
+
+    uint8_t    *p_buffer; /**< Payload start */
+    size_t      i_buffer; /**< Payload length */
+    uint8_t    *p_start; /**< Buffer start */
+    size_t      i_size; /**< Buffer total size */
+
+    const struct vlc_data_callbacks *cbs;
+};
+
+/**
+ * Initializes a custom data.
+ *
+ * This function initialize a data of timed data allocated by custom means.
+ * This allows passing data with copying even if the data has been allocated
+ * with unusual means or outside of LibVLC.
+ *
+ * Normally, datas are allocated and initialized by vlc_data_Alloc() instead.
+ *
+ * @param data allocated data structure to initialize
+ * @param cbs structure of custom callbacks to handle the data [IN]
+ * @param base start address of the datablock data
+ * @param length byte length of the datablock data
+ *
+ * @return @c data (this function cannot fail)
+ */
+VLC_API vlc_data_t *vlc_data_Init(vlc_data_t *data,
+                            const struct vlc_data_callbacks *cbs,
+                            void *base, size_t length);
+
+/**
+ * Allocates a datablock.
+ *
+ * Creates a new datablock with the requested size.
+ * The datablock must be released with vlc_data_Release().
+ *
+ * @param size size in bytes (possibly zero)
+ * @return the created datablock, or NULL on memory error.
+ */
+VLC_API vlc_data_t *vlc_data_Alloc(size_t size) VLC_USED VLC_MALLOC;
+
+VLC_API vlc_data_t *vlc_data_TryRealloc(vlc_data_t *, ssize_t pre, size_t body) VLC_USED;
+
+/**
+ * Reallocates a datablock.
+ *
+ * This function expands, shrinks or moves a data block.
+ * In many cases, this function can return without any memory allocation by
+ * reusing spare buffer space. Otherwise, a new datablock is created and data is
+ * copied.
+ *
+ * @param pre count of bytes to prepend if positive,
+ *            count of leading bytes to discard if negative
+ * @param body new bytes size of the datablock
+ *
+ * @return the reallocated datablock on succes, NULL on error.
+ *
+ * @note Skipping leading bytes can be achieved directly by subtracting from
+ * vlc_data_t.i_buffer and adding vlc_data_t.p_buffer.
+ * @note Discard trailing bytes can be achieved directly by subtracting from
+ * vlc_data_t.i_buffer.
+ * @note On error, the datablock is discarded.
+ * To avoid that, use vlc_data_TryRealloc() instead.
+ */
+VLC_API vlc_data_t *vlc_data_Realloc(vlc_data_t *, ssize_t pre, size_t body) VLC_USED;
+
+/**
+ * Releases a datablock.
+ *
+ * This function works for any @ref vlc_data_t datablock, regardless of the way it was
+ * allocated.
+ *
+ * @note
+ * If the datablock is in a chain, this function does <b>not</b> release any
+ * subsequent datablock in the chain. Use vlc_data_ChainRelease() for that purpose.
+ *
+ * @param datablock datablock to release (cannot be NULL)
+ */
+VLC_API void vlc_data_Release(vlc_data_t *data);
+
+/**
+ * Duplicates a datablock.
+ *
+ * Creates a writeable duplicate of a datablock.
+ *
+ * @return the duplicate on success, NULL on error.
+ */
+VLC_USED
+static inline vlc_data_t *vlc_data_Duplicate( const vlc_data_t *p_data )
+{
+    vlc_data_t *p_dup = vlc_data_Alloc( p_data->i_buffer );
+    if( p_dup == NULL )
+        return NULL;
+
+    memcpy( p_dup->p_buffer, p_data->p_buffer, p_data->i_buffer );
+
+    return p_dup;
+}
+
+/**
+ * Wraps heap in a data block.
+ *
+ * Creates a @ref vlc_data_t out of an existing heap allocation.
+ * This is provided by LibVLC so that manually heap-allocated blocks can safely
+ * be deallocated even after the origin plugin has been unloaded from memory.
+ *
+ * When vlc_data_Release() is called, VLC will free() the specified pointer.
+ *
+ * @param addr base address of the heap allocation (will be free()'d)
+ * @param length bytes length of the heap allocation
+ * @return NULL in case of error (ptr free()'d in that case), or a valid
+ * vlc_data_t pointer.
+ */
+VLC_API vlc_data_t *vlc_data_heap_Alloc(void *, size_t) VLC_USED VLC_MALLOC;
+
+/**
+ * Wraps a memory mapping in a data block
+ *
+ * Creates a @ref vlc_data_t from a virtual address memory mapping (mmap).
+ * This is provided by LibVLC so that mmap data blocks can safely be
+ * deallocated even after the allocating plugin has been unloaded from memory.
+ *
+ * @param addr base address of the mapping (as returned by mmap)
+ * @param length length (bytes) of the mapping (as passed to mmap)
+ * @return NULL if addr is MAP_FAILED, or an error occurred (in the later
+ * case, munmap(addr, length) is invoked before returning).
+ */
+VLC_API vlc_data_t *vlc_data_mmap_Alloc(void *addr, size_t length) VLC_USED VLC_MALLOC;
+
+/**
+ * Wraps a System V memory segment in a data block
+ *
+ * Creates a @ref vlc_data_t from a System V shared memory segment (shmget()).
+ * This is provided by LibVLC so that segments can safely be deallocated
+ * even after the allocating plugin has been unloaded from memory.
+ *
+ * @param addr base address of the segment (as returned by shmat())
+ * @param length length (bytes) of the segment (as passed to shmget())
+ * @return NULL if an error occurred (in that case, shmdt(addr) is invoked
+ * before returning NULL).
+ */
+VLC_API vlc_data_t * vlc_data_shm_Alloc(void *addr, size_t length) VLC_USED VLC_MALLOC;
+
+/**
+ * Maps a file handle in memory.
+ *
+ * Loads a file into a data block of memory through a file descriptor.
+ * If possible a private file mapping is created. Otherwise, the file is read
+ * normally. This function is a cancellation point.
+ *
+ * @note On 32-bits platforms,
+ * this function will not work for very large files,
+ * due to memory space constraints.
+ *
+ * @param fd file descriptor to load from
+ * @param write If true, request a read/write private mapping.
+ *              If false, request a read-only potentially shared mapping.
+ *
+ * @return a new data block with the file content at p_buffer, and file length at
+ * i_buffer (release it with vlc_data_Release()), or NULL upon error (see errno).
+ */
+VLC_API vlc_data_t *vlc_data_File(int fd, bool write) VLC_USED VLC_MALLOC;
+
+/**
+ * Maps a file in memory.
+ *
+ * Loads a file into a data block of memory from a path to the file.
+ * See also vlc_data_File().
+ *
+ * @param write If true, request a read/write private mapping.
+ *              If false, request a read-only potentially shared mapping.
+ */
+VLC_API vlc_data_t *vlc_data_FilePath(const char *, bool write) VLC_USED VLC_MALLOC;
+
+static inline void vlc_data_Cleanup (void * data)
+{
+    vlc_data_Release ((vlc_data_t *)data);
+}
+#define vlc_data_cleanup_push( data ) vlc_cleanup_push (vlc_data_Cleanup, data)
+
+/****************************************************************************
+ * Chains of data blocks functions helper
+ ****************************************************************************
+ * - vlc_data_ChainAppend : append a block to the last block of a chain. Try to
+ *      avoid using with a lot of data as it's really slow, prefer
+ *      vlc_data_ChainLastAppend, p_block can be NULL
+ * - vlc_data_ChainLastAppend : use a pointer over a pointer to the next blocks,
+ *      and update it.
+ * - vlc_data_ChainRelease : release a chain of block
+ * - vlc_data_ChainExtract : extract data from a chain, return real bytes counts
+ * - vlc_data_ChainGather : gather a chain, free it and return one block.
+ ****************************************************************************/
+static inline void vlc_data_ChainAppend( vlc_data_t **pp_list, vlc_data_t *p_block )
+{
+    if( *pp_list == NULL )
+    {
+        *pp_list = p_block;
+    }
+    else
+    {
+        vlc_data_t *p = *pp_list;
+
+        while( p->p_next ) p = p->p_next;
+        p->p_next = p_block;
+    }
+}
+
+static inline void vlc_data_ChainLastAppend( vlc_data_t ***ppp_last, vlc_data_t *p_block )
+{
+    vlc_data_t *p_last = p_block;
+
+    **ppp_last = p_block;
+
+    while( p_last->p_next ) p_last = p_last->p_next;
+    *ppp_last = &p_last->p_next;
+}
+
+static inline void vlc_data_ChainRelease( vlc_data_t *p_block )
+{
+    while( p_block )
+    {
+        vlc_data_t *p_next = p_block->p_next;
+        vlc_data_Release( p_block );
+        p_block = p_next;
+    }
+}
+
+static size_t vlc_data_ChainExtract( vlc_data_t *p_list, void *p_data, size_t i_max )
+{
+    size_t  i_total = 0;
+    uint8_t *p = (uint8_t*)p_data;
+
+    while( p_list && i_max )
+    {
+        size_t i_copy = __MIN( i_max, p_list->i_buffer );
+        memcpy( p, p_list->p_buffer, i_copy );
+        i_max   -= i_copy;
+        i_total += i_copy;
+        p       += i_copy;
+
+        p_list = p_list->p_next;
+    }
+    return i_total;
+}
+
+static inline void vlc_data_ChainProperties( vlc_data_t *p_list, int *pi_count, size_t *pi_size )
+{
+    size_t i_size = 0;
+    int i_count = 0;
+
+    while( p_list )
+    {
+        i_size += p_list->i_buffer;
+        i_count++;
+        p_list = p_list->p_next;
+    }
+
+    if( pi_size )
+        *pi_size = i_size;
+    if( pi_count )
+        *pi_count = i_count;
+}
+
+static inline vlc_data_t *vlc_data_ChainGather( vlc_data_t *p_list )
+{
+    size_t  i_total = 0;
+    vlc_data_t *g;
+
+    if( p_list->p_next == NULL )
+        return p_list;  /* Already gathered */
+
+    vlc_data_ChainProperties( p_list, NULL, &i_total);
+
+    g = vlc_data_Alloc( i_total );
+    if( !g )
+        return NULL;
+    vlc_data_ChainExtract( p_list, g->p_buffer, g->i_buffer );
+
+    /* free p_list */
+    vlc_data_ChainRelease( p_list );
+    return g;
+}
+
+/**
+ * @}
+ * \defgroup fifo data FIFO
+ * Thread-safe data queue functions
+ * @{
+ */
+typedef struct vlc_fifo_t vlc_data_fifo_t;
+/**
+ * Creates a thread-safe FIFO queue of datas.
+ *
+ * See also vlc_data_FifoPut() and vlc_data_FifoGet().
+ * The created queue must be released with vlc_data_FifoRelease().
+ *
+ * @return the FIFO or NULL on memory error
+ */
+VLC_API vlc_data_fifo_t *vlc_data_FifoNew(void) VLC_USED VLC_MALLOC VLC_DEPRECATED;
+
+/**
+ * Destroys a FIFO created by vlc_data_FifoNew().
+ *
+ * @note Any queued datas are also destroyed.
+ * @warning No other threads may be using the FIFO when this function is
+ * called. Otherwise, undefined behaviour will occur.
+ */
+VLC_API void vlc_data_FifoRelease(vlc_data_fifo_t *) VLC_DEPRECATED;
+
+/**
+ * Immediately queue one data at the end of a FIFO.
+ *
+ * @param fifo queue
+ * @param data head of a data list to queue (may be NULL)
+ */
+VLC_API void vlc_data_FifoPut(vlc_data_fifo_t *fifo, vlc_data_t *data) VLC_DEPRECATED;
+
+/**
+ * Dequeue the first data from the FIFO. If necessary, wait until there is
+ * one data in the queue. This function is (always) cancellation point.
+ *
+ * @return a valid data block
+ */
+VLC_API vlc_data_t *vlc_data_FifoGet(vlc_data_fifo_t *) VLC_USED VLC_DEPRECATED;
+
+VLC_API size_t vlc_data_FifoCount(vlc_data_fifo_t *) VLC_USED VLC_DEPRECATED;
+
+VLC_API vlc_data_t *vlc_data_FifoDequeueAllUnlocked(vlc_data_fifo_t *fifo) VLC_DEPRECATED;
+
+/** @} */
+
+/** @} */
+
+#endif /* VLC_DATA_H */
diff --git a/include/vlc_data_helper.h b/include/vlc_data_helper.h
new file mode 100644
index 0000000000..245f442359
--- /dev/null
+++ b/include/vlc_data_helper.h
@@ -0,0 +1,369 @@
+/*****************************************************************************
+ * vlc_data_helper.h: Helper functions for data blocks management.
+ *****************************************************************************
+ * Copyright (C) 2003-2017 VLC authors and VideoLAN
+ *
+ * Authors: Gildas Bazin <gbazin at netcourrier.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VLC_DATA_HELPER_H
+#define VLC_DATA_HELPER_H 1
+
+#include <vlc_data.h>
+
+typedef struct vlc_data_bytestream_t
+{
+    vlc_data_t *p_chain;  /**< byte stream head block */
+    vlc_data_t **pp_last; /**< tail ppointer for appends */
+    vlc_data_t *p_data;  /**< byte stream read pointer data */
+    size_t   i_data_offset; /**< byte stream read pointer offset within block */
+    size_t   i_base_offset; /**< block base offset (previous blocks total size) */
+    size_t   i_total;  /**< total bytes over all linked blocks */
+} vlc_data_bytestream_t;
+
+/*****************************************************************************
+ * vlc_data_bytestream_t management
+ *****************************************************************************/
+static inline void vlc_data_BytestreamInit( vlc_data_bytestream_t *p_bytestream )
+{
+    p_bytestream->p_chain = p_bytestream->p_data = NULL;
+    p_bytestream->pp_last = &p_bytestream->p_chain;
+    p_bytestream->i_data_offset = 0;
+    p_bytestream->i_base_offset = 0;
+    p_bytestream->i_total = 0;
+}
+
+static inline void vlc_data_BytestreamRelease( vlc_data_bytestream_t *p_bytestream )
+{
+    vlc_data_ChainRelease( p_bytestream->p_chain );
+}
+
+/**
+ * It flush all data (read and unread) from a vlc_data_bytestream_t.
+ */
+static inline void vlc_data_BytestreamEmpty( vlc_data_bytestream_t *p_bytestream )
+{
+    vlc_data_BytestreamRelease( p_bytestream );
+    vlc_data_BytestreamInit( p_bytestream );
+}
+
+/**
+ * It flushes all already read data from a vlc_data_bytestream_t.
+ */
+static inline void vlc_data_BytestreamFlush( vlc_data_bytestream_t *p_bytestream )
+{
+    vlc_data_t *data = p_bytestream->p_chain;
+
+    while( data != p_bytestream->p_data )
+    {
+        vlc_data_t *p_next = data->p_next;
+
+        p_bytestream->i_total -= data->i_buffer;
+        p_bytestream->i_base_offset -= data->i_buffer;
+        vlc_data_Release( data );
+        data = p_next;
+    }
+
+    while( data != NULL && data->i_buffer == p_bytestream->i_data_offset )
+    {
+        vlc_data_t *p_next = data->p_next;
+
+        p_bytestream->i_total -= data->i_buffer;
+        vlc_data_Release( data );
+        data = p_next;
+        p_bytestream->i_data_offset = 0;
+    }
+
+    p_bytestream->p_chain = p_bytestream->p_data = data;
+    if( p_bytestream->p_chain == NULL )
+        p_bytestream->pp_last = &p_bytestream->p_chain;
+}
+
+static inline void vlc_data_BytestreamPush( vlc_data_bytestream_t *p_bytestream,
+                                         vlc_data_t *p_data )
+{
+    vlc_data_ChainLastAppend( &p_bytestream->pp_last, p_data );
+    if( !p_bytestream->p_data ) p_bytestream->p_data = p_data;
+    for( ; p_data; p_data = p_data->p_next )
+        p_bytestream->i_total += p_data->i_buffer;
+}
+
+static inline size_t vlc_data_BytestreamRemaining( const vlc_data_bytestream_t *p_bytestream )
+{
+    return ( p_bytestream->i_total > p_bytestream->i_base_offset + p_bytestream->i_data_offset ) ?
+             p_bytestream->i_total - p_bytestream->i_base_offset - p_bytestream->i_data_offset : 0;
+}
+
+VLC_USED
+static inline vlc_data_t *vlc_data_BytestreamPop( vlc_data_bytestream_t *p_bytestream )
+{
+    vlc_data_t *p_data;
+
+    vlc_data_BytestreamFlush( p_bytestream );
+
+    p_data = p_bytestream->p_data;
+    if( unlikely( p_data == NULL ) )
+    {
+        return NULL;
+    }
+    else if( !p_data->p_next )
+    {
+        p_data->p_buffer += p_bytestream->i_data_offset;
+        p_data->i_buffer -= p_bytestream->i_data_offset;
+        p_bytestream->i_data_offset = 0;
+        p_bytestream->i_total = 0;
+        p_bytestream->p_chain = p_bytestream->p_data = NULL;
+        p_bytestream->pp_last = &p_bytestream->p_chain;
+        return p_data;
+    }
+
+    while( p_data->p_next && p_data->p_next->p_next )
+        p_data = p_data->p_next;
+
+    vlc_data_t *p_data_old = p_data;
+    p_data = p_data->p_next;
+    p_data_old->p_next = NULL;
+    p_bytestream->pp_last = &p_data_old->p_next;
+    if( p_data )
+        p_bytestream->i_total -= p_data->i_buffer;
+
+    return p_data;
+}
+
+static inline int vlc_data_WaitBytes( vlc_data_bytestream_t *p_bytestream,
+                                   size_t i_data )
+{
+    if( vlc_data_BytestreamRemaining( p_bytestream ) >= i_data )
+        return VLC_SUCCESS;
+    return VLC_EGENERIC;
+}
+
+static inline int vlc_data_PeekBytes( vlc_data_bytestream_t *p_bytestream,
+                                   uint8_t *p_data, size_t i_data )
+{
+    if( vlc_data_BytestreamRemaining( p_bytestream ) < i_data )
+        return VLC_EGENERIC;
+
+    /* Copy the data */
+    size_t i_offset = p_bytestream->i_data_offset;
+    size_t i_size = i_data;
+    for( vlc_data_t *p_frame = p_bytestream->p_data;
+         p_frame != NULL; p_frame = p_frame->p_next )
+    {
+        size_t i_copy = __MIN( i_size, p_frame->i_buffer - i_offset );
+        i_size -= i_copy;
+
+        if( i_copy )
+        {
+            memcpy( p_data, p_frame->p_buffer + i_offset, i_copy );
+            p_data += i_copy;
+        }
+
+        i_offset = 0;
+
+        if( !i_size ) break;
+    }
+
+    return VLC_SUCCESS;
+}
+
+static inline int vlc_data_GetBytes( vlc_data_bytestream_t *p_bytestream,
+                                  uint8_t *p_data, size_t i_data )
+{
+    if( vlc_data_BytestreamRemaining( p_bytestream ) < i_data )
+        return VLC_EGENERIC;
+
+    /* Copy the data */
+    size_t i_offset = p_bytestream->i_data_offset;
+    size_t i_size = i_data;
+    size_t i_copy = 0;
+    vlc_data_t *p_frame;
+    for( p_frame = p_bytestream->p_data;
+         p_frame != NULL; p_frame = p_frame->p_next )
+    {
+        i_copy = __MIN( i_size, p_frame->i_buffer - i_offset );
+        i_size -= i_copy;
+
+        if( i_copy && p_data != NULL )
+        {
+            memcpy( p_data, p_frame->p_buffer + i_offset, i_copy );
+            p_data += i_copy;
+        }
+
+        if( i_size == 0 )
+            break;
+
+        p_bytestream->i_base_offset += p_frame->i_buffer;
+        i_offset = 0;
+    }
+
+    p_bytestream->p_data = p_frame;
+    p_bytestream->i_data_offset = i_offset + i_copy;
+
+    return VLC_SUCCESS;
+}
+
+static inline int vlc_data_SkipBytes( vlc_data_bytestream_t *p_bytestream,
+                                   size_t i_data )
+{
+    return vlc_data_GetBytes( p_bytestream, NULL, i_data );
+}
+
+static inline int vlc_data_SkipByte( vlc_data_bytestream_t *p_bytestream )
+{
+    return vlc_data_GetBytes( p_bytestream, NULL, 1 );
+}
+
+static inline int vlc_data_PeekOffsetBytes( vlc_data_bytestream_t *p_bytestream,
+    size_t i_peek_offset, uint8_t *p_data, size_t i_data )
+{
+    const size_t i_remain = vlc_data_BytestreamRemaining( p_bytestream );
+    if( i_remain < i_data + i_peek_offset )
+        return VLC_EGENERIC;
+
+    /* Find the right place */
+    size_t i_offset = p_bytestream->i_data_offset;
+    size_t i_size = i_peek_offset;
+    size_t i_copy = 0;
+    vlc_data_t *p_frame;
+    for( p_frame = p_bytestream->p_data;
+         p_frame != NULL; p_frame = p_frame->p_next )
+    {
+        i_copy = __MIN( i_size, p_frame->i_buffer - i_offset );
+        i_size -= i_copy;
+
+        if( !i_size ) break;
+
+        i_offset = 0;
+    }
+
+    /* Copy the data */
+    i_offset += i_copy;
+    i_size = i_data;
+    for( ; p_frame != NULL; p_frame = p_frame->p_next )
+    {
+        i_copy = __MIN( i_size, p_frame->i_buffer - i_offset );
+        i_size -= i_copy;
+
+        if( i_copy )
+        {
+            memcpy( p_data, p_frame->p_buffer + i_offset, i_copy );
+            p_data += i_copy;
+        }
+
+        i_offset = 0;
+
+        if( !i_size ) break;
+    }
+
+    return VLC_SUCCESS;
+}
+
+typedef const uint8_t * (*vlc_data_startcode_helper_t)( const uint8_t *, const uint8_t * );
+typedef bool (*vlc_data_startcode_matcher_t)( uint8_t, size_t, const uint8_t * );
+
+static inline int vlc_data_FindStartcodeFromOffset(
+    vlc_data_bytestream_t *p_bytestream, size_t *pi_offset,
+    const uint8_t *p_startcode, int i_startcode_length,
+    vlc_data_startcode_helper_t p_startcode_helper,
+    vlc_data_startcode_matcher_t p_startcode_matcher )
+{
+    vlc_data_t *p_data, *p_data_backup = 0;
+    ssize_t i_size = 0;
+    size_t i_offset, i_offset_backup = 0;
+    int i_caller_offset_backup = 0, i_match;
+
+    /* Find the right place */
+    i_size = *pi_offset + p_bytestream->i_data_offset;
+    for( p_data = p_bytestream->p_data;
+         p_data != NULL; p_data = p_data->p_next )
+    {
+        i_size -= p_data->i_buffer;
+        if( i_size < 0 ) break;
+    }
+
+    if( unlikely( i_size >= 0 ) )
+    {
+        /* Not enough data, bail out */
+        return VLC_EGENERIC;
+    }
+
+    /* Begin the search.
+     * We first look for an occurrence of the 1st startcode byte and
+     * if found, we do a more thorough check. */
+    i_size += p_data->i_buffer;
+    *pi_offset -= i_size;
+    i_match = 0;
+    for( ; p_data != NULL; p_data = p_data->p_next )
+    {
+        for( i_offset = i_size; i_offset < p_data->i_buffer; i_offset++ )
+        {
+            /* Use optimized helper when possible */
+            if( p_startcode_helper && !i_match &&
+               (p_data->i_buffer - i_offset) > ((size_t)i_startcode_length - 1) )
+            {
+                const uint8_t *p_res = p_startcode_helper( &p_data->p_buffer[i_offset],
+                                                           &p_data->p_buffer[p_data->i_buffer] );
+                if( p_res )
+                {
+                    *pi_offset += i_offset + (p_res - &p_data->p_buffer[i_offset]);
+                    return VLC_SUCCESS;
+                }
+                /* Then parsing boundary with legacy code */
+                i_offset = p_data->i_buffer - (i_startcode_length - 1);
+            }
+
+            bool b_matched = ( p_startcode_matcher )
+                           ? p_startcode_matcher( p_data->p_buffer[i_offset], i_match, p_startcode )
+                           : p_data->p_buffer[i_offset] == p_startcode[i_match];
+            if( b_matched )
+            {
+                if( i_match == 0 )
+                {
+                    p_data_backup = p_data;
+                    i_offset_backup = i_offset;
+                    i_caller_offset_backup = *pi_offset;
+                }
+
+                if( i_match + 1 == i_startcode_length )
+                {
+                    /* We have it */
+                    *pi_offset += i_offset - i_match;
+                    return VLC_SUCCESS;
+                }
+
+                i_match++;
+            }
+            else if ( i_match > 0 )
+            {
+                /* False positive */
+                p_data = p_data_backup;
+                i_offset = i_offset_backup;
+                *pi_offset = i_caller_offset_backup;
+                i_match = 0;
+            }
+
+        }
+        i_size = 0;
+        *pi_offset += i_offset;
+    }
+
+    *pi_offset -= i_match;
+    return VLC_EGENERIC;
+}
+
+#endif /* vlc_data_HELPER_H */
diff --git a/include/vlc_demux.h b/include/vlc_demux.h
index 9930c0957d..f8979058dd 100644
--- a/include/vlc_demux.h
+++ b/include/vlc_demux.h
@@ -467,9 +467,9 @@ VLC_API void vlc_demux_chained_Delete(vlc_demux_chained_t *);
  *
  * This queues data for a chained demuxer to consume.
  *
- * \param block data block to queue
+ * \param frame timed data block to queue
  */
-VLC_API void vlc_demux_chained_Send(vlc_demux_chained_t *, block_t *block);
+VLC_API void vlc_demux_chained_Send(vlc_demux_chained_t *, vlc_data_t * block);
 
 /**
  * Controls a chained demuxer.
diff --git a/include/vlc_es_out.h b/include/vlc_es_out.h
index b690d570e9..5e36155703 100644
--- a/include/vlc_es_out.h
+++ b/include/vlc_es_out.h
@@ -125,7 +125,7 @@ enum es_out_policy_e
 struct es_out_callbacks
 {
     es_out_id_t *(*add)(es_out_t *, const es_format_t *);
-    int          (*send)(es_out_t *, es_out_id_t *, block_t *);
+    int          (*send)(es_out_t *, es_out_id_t *, vlc_frame_t *);
     void         (*del)(es_out_t *, es_out_id_t *);
     int          (*control)(es_out_t *, int query, va_list);
     void         (*destroy)(es_out_t *);
@@ -148,9 +148,9 @@ static inline void es_out_Del( es_out_t *out, es_out_id_t *id )
 }
 
 static inline int es_out_Send( es_out_t *out, es_out_id_t *id,
-                               block_t *p_block )
+                               vlc_frame_t *p_frame )
 {
-    return out->cbs->send( out, id, p_block );
+    return out->cbs->send( out, id, p_frame );
 }
 
 static inline int es_out_vaControl( es_out_t *out, int i_query, va_list args )
diff --git a/include/vlc_filter.h b/include/vlc_filter.h
index 65d2ea0e9f..336132d5e2 100644
--- a/include/vlc_filter.h
+++ b/include/vlc_filter.h
@@ -89,7 +89,7 @@ struct filter_t
         picture_t * (*pf_video_filter)( filter_t *, picture_t * );
 
         /** Filter an audio block (audio filter) */
-        block_t * (*pf_audio_filter)( filter_t *, block_t * );
+        vlc_frame_t * (*pf_audio_filter)( filter_t *, vlc_frame_t * );
 
         /** Blend a subpicture onto a picture (blend) */
         void (*pf_video_blend)( filter_t *,  picture_t *, const picture_t *,
@@ -110,7 +110,7 @@ struct filter_t
     {
         /* TODO: video filter drain */
         /** Drain (audio filter) */
-        block_t *(*pf_audio_drain) ( filter_t * );
+        vlc_frame_t *(*pf_audio_drain) ( filter_t * );
     };
 
     /** Flush
@@ -190,7 +190,7 @@ static inline void filter_ChangeViewpoint( filter_t *p_filter,
 /**
  * This function will drain, then flush an audio filter.
  */
-static inline block_t *filter_DrainAudio( filter_t *p_filter )
+static inline vlc_frame_t *filter_DrainAudio( filter_t *p_filter )
 {
     if( p_filter->pf_audio_drain )
         return p_filter->pf_audio_drain( p_filter );
diff --git a/include/vlc_block.h b/include/vlc_frame.h
similarity index 54%
rename from include/vlc_block.h
rename to include/vlc_frame.h
index 1b47e7329f..8af9d7d2fa 100644
--- a/include/vlc_block.h
+++ b/include/vlc_frame.h
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * vlc_block.h: Data blocks management functions
+ * vlc_frame.h: Data blocks management functions
  *****************************************************************************
  * Copyright (C) 2003 VLC authors and VideoLAN
  *
@@ -20,16 +20,16 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
-#ifndef VLC_BLOCK_H
-#define VLC_BLOCK_H 1
+#ifndef VLC_FRAME_H
+#define VLC_FRAME_H 1
 
 /**
- * \defgroup block Data blocks
+ * \defgroup frame Timed Data blocks
  * \ingroup input
  *
- * Blocks of binary data.
+ * Frames of timed binary data.
  *
- * @ref block_t is a generic structure to represent a binary blob within VLC.
+ * @ref vlc_frame_t is a generic structure to represent a binary blob within VLC.
  * The primary goal of the structure is to avoid memory copying as data is
  * passed around. It is notably used between the \ref demux, the packetizer
  * (if present) and the \ref decoder, and for audio, between the \ref decoder,
@@ -37,13 +37,13 @@
  *
  * @{
  * \file
- * Data block definition and functions
+ * Data frame definition and functions
  */
 
 #include <sys/types.h>  /* for ssize_t */
 
 /****************************************************************************
- * block:
+ * frame:
  ****************************************************************************
  * - i_flags may not always be set (ie could be 0, even for a key frame
  *      it depends where you receive the buffer (before/after a packetizer
@@ -54,74 +54,76 @@
  *
  * - i_buffer number of valid data pointed by p_buffer
  *      you can freely decrease it but never increase it yourself
- *      (use block_Realloc)
+ *      (use vlc_frame_Realloc)
  * - p_buffer: pointer over datas. You should never overwrite it, you can
- *   only incremment it to skip datas, in others cases use block_Realloc
- *   (don't duplicate yourself in a bigger buffer, block_Realloc is
+ *   only incremment it to skip datas, in others cases use vlc_frame_Realloc
+ *   (don't duplicate yourself in a bigger buffer, vlc_frame_Realloc is
  *   optimised for preheader/postdatas increase)
  ****************************************************************************/
 
-/** The content doesn't follow the last block, possible some blocks in between
+/** The content doesn't follow the last frame, possible some frames in between
  *  have been lost */
-#define BLOCK_FLAG_DISCONTINUITY 0x0001
+#define FRAME_FLAG_DISCONTINUITY 0x0001
 /** Intra frame */
-#define BLOCK_FLAG_TYPE_I        0x0002
+#define FRAME_FLAG_TYPE_I        0x0002
 /** Inter frame with backward reference only */
-#define BLOCK_FLAG_TYPE_P        0x0004
+#define FRAME_FLAG_TYPE_P        0x0004
 /** Inter frame with backward and forward reference */
-#define BLOCK_FLAG_TYPE_B        0x0008
+#define FRAME_FLAG_TYPE_B        0x0008
 /** For inter frame when you don't know the real type */
-#define BLOCK_FLAG_TYPE_PB       0x0010
-/** Warn that this block is a header one */
-#define BLOCK_FLAG_HEADER        0x0020
-/** This block contains the last part of a sequence  */
-#define BLOCK_FLAG_END_OF_SEQUENCE 0x0040
-/** This block contains a clock reference */
-#define BLOCK_FLAG_CLOCK         0x0080
-/** This block is scrambled */
-#define BLOCK_FLAG_SCRAMBLED     0x0100
-/** This block has to be decoded but not be displayed */
-#define BLOCK_FLAG_PREROLL       0x0200
-/** This block is corrupted and/or there is data loss  */
-#define BLOCK_FLAG_CORRUPTED     0x0400
+#define FRAME_FLAG_TYPE_PB       0x0010
+/** Warn that this frame is a header one */
+#define FRAME_FLAG_HEADER        0x0020
+/** This frame contains the last part of a sequence  */
+#define FRAME_FLAG_END_OF_SEQUENCE 0x0040
+/** This frame contains a clock reference */
+#define FRAME_FLAG_CLOCK         0x0080
+/** This frame is scrambled */
+#define FRAME_FLAG_SCRAMBLED     0x0100
+/** This frame has to be decoded but not be displayed */
+#define FRAME_FLAG_PREROLL       0x0200
+/** This frame is corrupted and/or there is data loss  */
+#define FRAME_FLAG_CORRUPTED     0x0400
 /** This block is last of its access unit */
-#define BLOCK_FLAG_AU_END        0x0800
-/** This block contains an interlaced picture with top field stored first */
-#define BLOCK_FLAG_TOP_FIELD_FIRST 0x1000
-/** This block contains an interlaced picture with bottom field stored first */
-#define BLOCK_FLAG_BOTTOM_FIELD_FIRST 0x2000
-/** This block contains a single field from interlaced picture. */
-#define BLOCK_FLAG_SINGLE_FIELD  0x4000
+#define FRAME_FLAG_AU_END        0x0800
+/** This frame contains an interlaced picture with top field stored first */
+#define FRAME_FLAG_TOP_FIELD_FIRST 0x1000
+/** This frame contains an interlaced picture with bottom field stored first */
+#define FRAME_FLAG_BOTTOM_FIELD_FIRST 0x2000
+/** This frame contains a single field from interlaced picture. */
+#define FRAME_FLAG_SINGLE_FIELD  0x4000
 
-/** This block contains an interlaced picture */
-#define BLOCK_FLAG_INTERLACED_MASK \
-    (BLOCK_FLAG_TOP_FIELD_FIRST|BLOCK_FLAG_BOTTOM_FIELD_FIRST|BLOCK_FLAG_SINGLE_FIELD)
+/** This frame contains an interlaced picture */
+#define FRAME_FLAG_INTERLACED_MASK \
+    (FRAME_FLAG_TOP_FIELD_FIRST|FRAME_FLAG_BOTTOM_FIELD_FIRST|FRAME_FLAG_SINGLE_FIELD)
 
-#define BLOCK_FLAG_TYPE_MASK \
-    (BLOCK_FLAG_TYPE_I|BLOCK_FLAG_TYPE_P|BLOCK_FLAG_TYPE_B|BLOCK_FLAG_TYPE_PB)
+#define FRAME_FLAG_TYPE_MASK \
+    (FRAME_FLAG_TYPE_I|FRAME_FLAG_TYPE_P|FRAME_FLAG_TYPE_B|FRAME_FLAG_TYPE_PB)
 
 /* These are for input core private usage only */
-#define BLOCK_FLAG_CORE_PRIVATE_MASK  0x00ff0000
-#define BLOCK_FLAG_CORE_PRIVATE_SHIFT 16
+#define FRAME_FLAG_CORE_PRIVATE_MASK  0x00ff0000
+#define FRAME_FLAG_CORE_PRIVATE_SHIFT 16
 
 /* These are for module private usage only */
-#define BLOCK_FLAG_PRIVATE_MASK  0xff000000
-#define BLOCK_FLAG_PRIVATE_SHIFT 24
+#define FRAME_FLAG_PRIVATE_MASK  0xff000000
+#define FRAME_FLAG_PRIVATE_SHIFT 24
 
-struct vlc_block_callbacks
+struct vlc_frame_callbacks
 {
-    void (*free)(block_t *);
+    void (*free)(vlc_frame_t *);
 };
 
-struct block_t
+struct vlc_frame_t
 {
-    block_t    *p_next;
+    vlc_frame_t    *p_next;
 
     uint8_t    *p_buffer; /**< Payload start */
     size_t      i_buffer; /**< Payload length */
     uint8_t    *p_start; /**< Buffer start */
     size_t      i_size; /**< Buffer total size */
 
+    const struct vlc_frame_callbacks *cbs;
+
     uint32_t    i_flags;
     unsigned    i_nb_samples; /* Used for audio */
 
@@ -129,80 +131,79 @@ struct block_t
     vlc_tick_t  i_dts;
     vlc_tick_t  i_length;
 
-    const struct vlc_block_callbacks *cbs;
 };
 
 /**
- * Initializes a custom block.
+ * Initializes a custom frame.
  *
- * This function initialize a block of timed data allocated by custom means.
+ * This function initialize a frame of timed data allocated by custom means.
  * This allows passing data with copying even if the data has been allocated
  * with unusual means or outside of LibVLC.
  *
- * Normally, blocks are allocated and initialized by block_Alloc() instead.
+ * Normally, frames are allocated and initialized by frame_Alloc() instead.
  *
- * @param block allocated block structure to initialize
- * @param cbs structure of custom callbacks to handle the block [IN]
- * @param base start address of the block data
- * @param length byte length of the block data
+ * @param frame allocated frame structure to initialize
+ * @param cbs structure of custom callbacks to handle the frame [IN]
+ * @param base start address of the frame data
+ * @param length byte length of the frame data
  *
- * @return @c block (this function cannot fail)
+ * @return @c frame (this function cannot fail)
  */
-VLC_API block_t *block_Init(block_t *block,
-                            const struct vlc_block_callbacks *cbs,
+VLC_API vlc_frame_t *vlc_frame_Init(vlc_frame_t *frame,
+                            const struct vlc_frame_callbacks *cbs,
                             void *base, size_t length);
 
 /**
- * Allocates a block.
+ * Allocates a frame.
  *
- * Creates a new block with the requested size.
- * The block must be released with block_Release().
+ * Creates a new frame with the requested size.
+ * The frame must be released with frame_Release().
  *
  * @param size size in bytes (possibly zero)
- * @return the created block, or NULL on memory error.
+ * @return the created frame, or NULL on memory error.
  */
-VLC_API block_t *block_Alloc(size_t size) VLC_USED VLC_MALLOC;
+VLC_API vlc_frame_t *vlc_frame_Alloc(size_t size) VLC_USED VLC_MALLOC;
 
-VLC_API block_t *block_TryRealloc(block_t *, ssize_t pre, size_t body) VLC_USED;
+VLC_API vlc_frame_t *vlc_frame_TryRealloc(vlc_frame_t *, ssize_t pre, size_t body) VLC_USED;
 
 /**
- * Reallocates a block.
+ * Reallocates a frame.
  *
- * This function expands, shrinks or moves a data block.
+ * This function expands, shrinks or moves a data frame.
  * In many cases, this function can return without any memory allocation by
- * reusing spare buffer space. Otherwise, a new block is created and data is
+ * reusing spare buffer space. Otherwise, a new frame is created and data is
  * copied.
  *
  * @param pre count of bytes to prepend if positive,
  *            count of leading bytes to discard if negative
- * @param body new bytes size of the block
+ * @param body new bytes size of the frame
  *
- * @return the reallocated block on succes, NULL on error.
+ * @return the reallocated frame on succes, NULL on error.
  *
  * @note Skipping leading bytes can be achieved directly by subtracting from
- * block_t.i_buffer and adding block_t.p_buffer.
+ * vlc_frame_t.i_buffer and adding vlc_frame_t.p_buffer.
  * @note Discard trailing bytes can be achieved directly by subtracting from
- * block_t.i_buffer.
- * @note On error, the block is discarded.
- * To avoid that, use block_TryRealloc() instead.
+ * vlc_frame_t.i_buffer.
+ * @note On error, the frame is discarded.
+ * To avoid that, use vlc_frame_TryRealloc() instead.
  */
-VLC_API block_t *block_Realloc(block_t *, ssize_t pre, size_t body) VLC_USED;
+VLC_API vlc_frame_t *vlc_frame_Realloc(vlc_frame_t *, ssize_t pre, size_t body) VLC_USED;
 
 /**
- * Releases a block.
+ * Releases a frame.
  *
- * This function works for any @ref block_t block, regardless of the way it was
+ * This function works for any @ref vlc_frame_t frame, regardless of the way it was
  * allocated.
  *
  * @note
- * If the block is in a chain, this function does <b>not</b> release any
- * subsequent block in the chain. Use block_ChainRelease() for that purpose.
+ * If the frame is in a chain, this function does <b>not</b> release any
+ * subsequent frame in the chain. Use vlc_frame_ChainRelease() for that purpose.
  *
- * @param block block to release (cannot be NULL)
+ * @param frame frame to release (cannot be NULL)
  */
-VLC_API void block_Release(block_t *block);
+VLC_API void vlc_frame_Release(vlc_frame_t *frame);
 
-static inline void block_CopyProperties( block_t *dst, const block_t *src )
+static inline void vlc_frame_CopyProperties( vlc_frame_t *dst, const vlc_frame_t *src )
 {
     dst->i_flags   = src->i_flags;
     dst->i_nb_samples = src->i_nb_samples;
@@ -212,46 +213,46 @@ static inline void block_CopyProperties( block_t *dst, const block_t *src )
 }
 
 /**
- * Duplicates a block.
+ * Duplicates a frame.
  *
- * Creates a writeable duplicate of a block.
+ * Creates a writeable duplicate of a frame.
  *
  * @return the duplicate on success, NULL on error.
  */
 VLC_USED
-static inline block_t *block_Duplicate( const block_t *p_block )
+static inline vlc_frame_t *vlc_frame_Duplicate( const vlc_frame_t *p_frame )
 {
-    block_t *p_dup = block_Alloc( p_block->i_buffer );
+    vlc_frame_t *p_dup = vlc_frame_Alloc( p_frame->i_buffer );
     if( p_dup == NULL )
         return NULL;
 
-    block_CopyProperties( p_dup, p_block );
-    memcpy( p_dup->p_buffer, p_block->p_buffer, p_block->i_buffer );
+    vlc_frame_CopyProperties( p_dup, p_frame );
+    memcpy( p_dup->p_buffer, p_frame->p_buffer, p_frame->i_buffer );
 
     return p_dup;
 }
 
 /**
- * Wraps heap in a block.
+ * Wraps heap in a frame.
  *
- * Creates a @ref block_t out of an existing heap allocation.
- * This is provided by LibVLC so that manually heap-allocated blocks can safely
+ * Creates a @ref vlc_frame_t out of an existing heap allocation.
+ * This is provided by LibVLC so that manually heap-allocated frames can safely
  * be deallocated even after the origin plugin has been unloaded from memory.
  *
- * When block_Release() is called, VLC will free() the specified pointer.
+ * When vlc_frame_Release() is called, VLC will free() the specified pointer.
  *
  * @param addr base address of the heap allocation (will be free()'d)
  * @param length bytes length of the heap allocation
  * @return NULL in case of error (ptr free()'d in that case), or a valid
- * block_t pointer.
+ * vlc_frame_t pointer.
  */
-VLC_API block_t *block_heap_Alloc(void *, size_t) VLC_USED VLC_MALLOC;
+VLC_API vlc_frame_t *vlc_frame_heap_Alloc(void *, size_t) VLC_USED VLC_MALLOC;
 
 /**
- * Wraps a memory mapping in a block
+ * Wraps a memory mapping in a frame
  *
- * Creates a @ref block_t from a virtual address memory mapping (mmap).
- * This is provided by LibVLC so that mmap blocks can safely be deallocated
+ * Creates a @ref vlc_frame_t from a virtual address memory mapping (mmap).
+ * This is provided by LibVLC so that mmap frames can safely be deallocated
  * even after the allocating plugin has been unloaded from memory.
  *
  * @param addr base address of the mapping (as returned by mmap)
@@ -259,12 +260,12 @@ VLC_API block_t *block_heap_Alloc(void *, size_t) VLC_USED VLC_MALLOC;
  * @return NULL if addr is MAP_FAILED, or an error occurred (in the later
  * case, munmap(addr, length) is invoked before returning).
  */
-VLC_API block_t *block_mmap_Alloc(void *addr, size_t length) VLC_USED VLC_MALLOC;
+VLC_API vlc_frame_t *vlc_frame_mmap_Alloc(void *addr, size_t length) VLC_USED VLC_MALLOC;
 
 /**
- * Wraps a System V memory segment in a block
+ * Wraps a System V memory segment in a frame
  *
- * Creates a @ref block_t from a System V shared memory segment (shmget()).
+ * Creates a @ref vlc_frame_t from a System V shared memory segment (shmget()).
  * This is provided by LibVLC so that segments can safely be deallocated
  * even after the allocating plugin has been unloaded from memory.
  *
@@ -273,12 +274,12 @@ VLC_API block_t *block_mmap_Alloc(void *addr, size_t length) VLC_USED VLC_MALLOC
  * @return NULL if an error occurred (in that case, shmdt(addr) is invoked
  * before returning NULL).
  */
-VLC_API block_t * block_shm_Alloc(void *addr, size_t length) VLC_USED VLC_MALLOC;
+VLC_API vlc_frame_t * vlc_frame_shm_Alloc(void *addr, size_t length) VLC_USED VLC_MALLOC;
 
 /**
  * Maps a file handle in memory.
  *
- * Loads a file into a block of memory through a file descriptor.
+ * Loads a file into a frame of memory through a file descriptor.
  * If possible a private file mapping is created. Otherwise, the file is read
  * normally. This function is a cancellation point.
  *
@@ -290,81 +291,81 @@ VLC_API block_t * block_shm_Alloc(void *addr, size_t length) VLC_USED VLC_MALLOC
  * @param write If true, request a read/write private mapping.
  *              If false, request a read-only potentially shared mapping.
  *
- * @return a new block with the file content at p_buffer, and file length at
- * i_buffer (release it with block_Release()), or NULL upon error (see errno).
+ * @return a new frame with the file content at p_buffer, and file length at
+ * i_buffer (release it with vlc_frame_Release()), or NULL upon error (see errno).
  */
-VLC_API block_t *block_File(int fd, bool write) VLC_USED VLC_MALLOC;
+VLC_API vlc_frame_t *vlc_frame_File(int fd, bool write) VLC_USED VLC_MALLOC;
 
 /**
  * Maps a file in memory.
  *
- * Loads a file into a block of memory from a path to the file.
- * See also block_File().
+ * Loads a file into a frame of memory from a path to the file.
+ * See also vlc_frame_File().
  *
  * @param write If true, request a read/write private mapping.
  *              If false, request a read-only potentially shared mapping.
  */
-VLC_API block_t *block_FilePath(const char *, bool write) VLC_USED VLC_MALLOC;
+VLC_API vlc_frame_t *vlc_frame_FilePath(const char *, bool write) VLC_USED VLC_MALLOC;
 
-static inline void block_Cleanup (void *block)
+static inline void vlc_frame_Cleanup (void *frame)
 {
-    block_Release ((block_t *)block);
+    vlc_frame_Release ((vlc_frame_t *)frame);
 }
-#define block_cleanup_push( block ) vlc_cleanup_push (block_Cleanup, block)
+#define vlc_frame_cleanup_push( frame ) vlc_cleanup_push (vlc_frame_Cleanup, frame)
 
 /**
- * \defgroup block_fifo Block chain
+ * \defgroup vlc_frame_fifo frame chain
  * @{
  */
 
 /****************************************************************************
- * Chains of blocks functions helper
+ * Chains of frames functions helper
  ****************************************************************************
- * - block_ChainAppend : append a block to the last block of a chain. Try to
+ * - vlc_frame_ChainAppend : append a frame to the last frame of a chain. Try to
  *      avoid using with a lot of data as it's really slow, prefer
- *      block_ChainLastAppend, p_block can be NULL
- * - block_ChainLastAppend : use a pointer over a pointer to the next blocks,
+ *      vlc_frame_ChainLastAppend, p_frame can be NULL
+ * - vlc_frame_ChainLastAppend : use a pointer over a pointer to the next frames,
  *      and update it.
- * - block_ChainRelease : release a chain of block
- * - block_ChainExtract : extract data from a chain, return real bytes counts
- * - block_ChainGather : gather a chain, free it and return one block.
+ * - vlc_frame_ChainRelease : release a chain of frame
+ * - vlc_frame_ChainExtract : extract data from a chain, return real bytes counts
+ * - vlc_frame_ChainGather : gather a chain, free it and return one frame.
  ****************************************************************************/
-static inline void block_ChainAppend( block_t **pp_list, block_t *p_block )
+static inline void vlc_frame_ChainAppend( vlc_frame_t **pp_list, vlc_frame_t *p_frame )
 {
     if( *pp_list == NULL )
     {
-        *pp_list = p_block;
+        *pp_list = p_frame;
     }
     else
     {
-        block_t *p = *pp_list;
+        vlc_frame_t *p = *pp_list;
 
         while( p->p_next ) p = p->p_next;
-        p->p_next = p_block;
+        p->p_next = p_frame;
     }
 }
 
-static inline void block_ChainLastAppend( block_t ***ppp_last, block_t *p_block )
+static inline void vlc_frame_ChainLastAppend( vlc_frame_t ***ppp_last, vlc_frame_t *p_frame )
 {
-    block_t *p_last = p_block;
+    vlc_frame_t *p_last = p_frame;
 
-    **ppp_last = p_block;
+    **ppp_last = p_frame;
 
     while( p_last->p_next ) p_last = p_last->p_next;
     *ppp_last = &p_last->p_next;
 }
 
-static inline void block_ChainRelease( block_t *p_block )
+static inline void vlc_frame_ChainRelease( vlc_frame_t *p_frame )
 {
-    while( p_block )
+    while( p_frame )
     {
-        block_t *p_next = p_block->p_next;
-        block_Release( p_block );
-        p_block = p_next;
+        vlc_frame_t *p_next = p_frame->p_next;
+        vlc_frame_Release( p_frame );
+        p_frame = p_next;
     }
 }
 
-static size_t block_ChainExtract( block_t *p_list, void *p_data, size_t i_max )
+static size_t vlc_frame_ChainExtract( vlc_frame_t *p_list, void *p_data, size_t i_max )
 {
     size_t  i_total = 0;
     uint8_t *p = (uint8_t*)p_data;
@@ -382,7 +383,7 @@ static size_t block_ChainExtract( block_t *p_list, void *p_data, size_t i_max )
     return i_total;
 }
 
-static inline void block_ChainProperties( block_t *p_list, int *pi_count, size_t *pi_size, vlc_tick_t *pi_length )
+static inline void vlc_frame_ChainProperties( vlc_frame_t *p_list, int *pi_count, size_t *pi_size, vlc_tick_t *pi_length )
 {
     size_t i_size = 0;
     vlc_tick_t i_length = 0;
@@ -405,21 +406,21 @@ static inline void block_ChainProperties( block_t *p_list, int *pi_count, size_t
         *pi_count = i_count;
 }
 
-static inline block_t *block_ChainGather( block_t *p_list )
+static inline vlc_frame_t *vlc_frame_ChainGather( vlc_frame_t *p_list )
 {
     size_t  i_total = 0;
     vlc_tick_t i_length = 0;
-    block_t *g;
+    vlc_frame_t *g;
 
     if( p_list->p_next == NULL )
         return p_list;  /* Already gathered */
 
-    block_ChainProperties( p_list, NULL, &i_total, &i_length );
+    vlc_frame_ChainProperties( p_list, NULL, &i_total, &i_length );
 
-    g = block_Alloc( i_total );
+    g = vlc_frame_Alloc( i_total );
     if( !g )
         return NULL;
-    block_ChainExtract( p_list, g->p_buffer, g->i_buffer );
+    vlc_frame_ChainExtract( p_list, g->p_buffer, g->i_buffer );
 
     g->i_flags = p_list->i_flags;
     g->i_pts   = p_list->i_pts;
@@ -427,77 +428,79 @@ static inline block_t *block_ChainGather( block_t *p_list )
     g->i_length = i_length;
 
     /* free p_list */
-    block_ChainRelease( p_list );
+    vlc_frame_ChainRelease( p_list );
     return g;
 }
 
 /**
  * @}
- * \defgroup fifo Block FIFO
- * Thread-safe block queue functions
+ * \defgroup fifo frame FIFO
+ * Thread-safe frame queue functions
  * @{
  */
 
+typedef struct vlc_fifo_t vlc_frame_fifo_t;
+typedef struct vlc_fifo_t vlc_fifo_t;
 /**
- * Creates a thread-safe FIFO queue of blocks.
+ * Creates a thread-safe FIFO queue of frames.
  *
- * See also block_FifoPut() and block_FifoGet().
- * The created queue must be released with block_FifoRelease().
+ * See also vlc_frame_FifoPut() and vlc_frame_FifoGet().
+ * The created queue must be released with vlc_frame_FifoRelease().
  *
  * @return the FIFO or NULL on memory error
  */
-VLC_API block_fifo_t *block_FifoNew(void) VLC_USED VLC_MALLOC;
+VLC_API vlc_frame_fifo_t *vlc_frame_FifoNew(void) VLC_USED VLC_MALLOC;
 
 /**
- * Destroys a FIFO created by block_FifoNew().
+ * Destroys a FIFO created by vlc_frame_FifoNew().
  *
- * @note Any queued blocks are also destroyed.
+ * @note Any queued frames are also destroyed.
  * @warning No other threads may be using the FIFO when this function is
  * called. Otherwise, undefined behaviour will occur.
  */
-VLC_API void block_FifoRelease(block_fifo_t *);
+VLC_API void vlc_frame_FifoRelease(vlc_frame_fifo_t *);
 
 /**
- * Clears all blocks in a FIFO.
+ * Clears all frames in a FIFO.
  */
-VLC_API void block_FifoEmpty(block_fifo_t *);
+VLC_API void vlc_frame_FifoEmpty(vlc_frame_fifo_t *);
 
 /**
- * Immediately queue one block at the end of a FIFO.
+ * Immediately queue one frame at the end of a FIFO.
  *
  * @param fifo queue
- * @param block head of a block list to queue (may be NULL)
+ * @param frame head of a frame list to queue (may be NULL)
  */
-VLC_API void block_FifoPut(block_fifo_t *fifo, block_t *block);
+VLC_API void vlc_frame_FifoPut(vlc_frame_fifo_t *fifo, vlc_frame_t *frame);
 
 /**
- * Dequeue the first block from the FIFO. If necessary, wait until there is
- * one block in the queue. This function is (always) cancellation point.
+ * Dequeue the first frame from the FIFO. If necessary, wait until there is
+ * one frame in the queue. This function is (always) cancellation point.
  *
- * @return a valid block
+ * @return a valid frame
  */
-VLC_API block_t *block_FifoGet(block_fifo_t *) VLC_USED;
+VLC_API vlc_frame_t *vlc_frame_FifoGet(vlc_frame_fifo_t *) VLC_USED;
 
 /**
- * Peeks the first block in the FIFO.
+ * Peeks the first frame in the FIFO.
  *
- * @warning This function leaves the block in the FIFO.
- * You need to protect against concurrent threads who could dequeue the block.
+ * @warning This function leaves the frame in the FIFO.
+ * You need to protect against concurrent threads who could dequeue the frame.
  * Preferably, there should be only one thread reading from the FIFO.
  *
  * @warning This function is undefined if the FIFO is empty.
  *
- * @return a valid block.
+ * @return a valid frame.
  */
-VLC_API block_t *block_FifoShow(block_fifo_t *);
+VLC_API vlc_frame_t *vlc_frame_FifoShow(vlc_frame_fifo_t *);
+
+size_t vlc_frame_FifoSize(vlc_frame_fifo_t *) VLC_USED VLC_DEPRECATED;
+VLC_API size_t vlc_frame_FifoCount(vlc_frame_fifo_t *) VLC_USED VLC_DEPRECATED;
 
-size_t block_FifoSize(block_fifo_t *) VLC_USED VLC_DEPRECATED;
-VLC_API size_t block_FifoCount(block_fifo_t *) VLC_USED VLC_DEPRECATED;
 
-typedef struct block_fifo_t vlc_fifo_t;
 
 /**
- * Locks a block FIFO.
+ * Locks a frame FIFO.
  *
  * No more than one thread can lock the FIFO at any given
  * time, and no other thread can modify the FIFO while it is locked.
@@ -512,7 +515,7 @@ typedef struct block_fifo_t vlc_fifo_t;
 VLC_API void vlc_fifo_Lock(vlc_fifo_t *);
 
 /**
- * Unlocks a block FIFO.
+ * Unlocks a frame FIFO.
  *
  * The calling thread must have locked the FIFO previously with
  * vlc_fifo_Lock(). Otherwise, the behaviour is undefined.
@@ -535,7 +538,7 @@ VLC_API void vlc_fifo_Signal(vlc_fifo_t *);
  * Waits on the FIFO.
  *
  * Atomically unlocks the FIFO and waits until one thread signals the FIFO,
- * then locks the FIFO again. A signal can be sent by queueing a block to the
+ * then locks the FIFO again. A signal can be sent by queueing a frame to the
  * previously empty FIFO or by calling vlc_fifo_Signal() directly.
  * This function may also return spuriously at any moment.
  *
@@ -555,9 +558,9 @@ VLC_API void vlc_fifo_WaitCond(vlc_fifo_t *, vlc_cond_t *);
 int vlc_fifo_TimedWaitCond(vlc_fifo_t *, vlc_cond_t *, vlc_tick_t);
 
 /**
- * Queues a linked-list of blocks into a locked FIFO.
+ * Queues a linked-list of frames into a locked FIFO.
  *
- * @param block the head of the list of blocks
+ * @param frame the head of the list of frames
  *              (if NULL, this function has no effects)
  *
  * @note This function is not a cancellation point.
@@ -565,22 +568,22 @@ int vlc_fifo_TimedWaitCond(vlc_fifo_t *, vlc_cond_t *, vlc_tick_t);
  * @warning The FIFO must be locked by the calling thread using
  * vlc_fifo_Lock(). Otherwise behaviour is undefined.
  */
-VLC_API void vlc_fifo_QueueUnlocked(vlc_fifo_t *, block_t *);
+VLC_API void vlc_frame_FifoQueueUnlocked(vlc_fifo_t *, vlc_frame_t *);
 
 /**
- * Dequeues the first block from a locked FIFO, if any.
+ * Dequeues the first frame from a locked FIFO, if any.
  *
  * @note This function is not a cancellation point.
  *
  * @warning The FIFO must be locked by the calling thread using
  * vlc_fifo_Lock(). Otherwise behaviour is undefined.
  *
- * @return the first block in the FIFO or NULL if the FIFO is empty
+ * @return the first frame in the FIFO or NULL if the FIFO is empty
  */
-VLC_API block_t *vlc_fifo_DequeueUnlocked(vlc_fifo_t *) VLC_USED;
+VLC_API vlc_frame_t *vlc_frame_FifoDequeueUnlocked(vlc_fifo_t *) VLC_USED;
 
 /**
- * Dequeues the all blocks from a locked FIFO.
+ * Dequeues the all frames from a locked FIFO.
  *
  * This is equivalent to calling vlc_fifo_DequeueUnlocked() repeatedly until
  * the FIFO is emptied, but this function is much faster.
@@ -590,21 +593,21 @@ VLC_API block_t *vlc_fifo_DequeueUnlocked(vlc_fifo_t *) VLC_USED;
  * @warning The FIFO must be locked by the calling thread using
  * vlc_fifo_Lock(). Otherwise behaviour is undefined.
  *
- * @return a linked-list of all blocks in the FIFO (possibly NULL)
+ * @return a linked-list of all frames in the FIFO (possibly NULL)
  */
-VLC_API block_t *vlc_fifo_DequeueAllUnlocked(vlc_fifo_t *) VLC_USED;
+VLC_API vlc_frame_t *vlc_frame_FifoDequeueAllUnlocked(vlc_fifo_t *) VLC_USED;
 
 /**
- * Counts blocks in a FIFO.
+ * Counts frames in a FIFO.
  *
- * Checks how many blocks are queued in a locked FIFO.
+ * Checks how many frames are queued in a locked FIFO.
  *
  * @note This function is not cancellation point.
  *
  * @warning The FIFO must be locked by the calling thread using
  * vlc_fifo_Lock(). Otherwise behaviour is undefined.
  *
- * @return the number of blocks in the FIFO (zero if it is empty)
+ * @return the number of frames in the FIFO (zero if it is empty)
  */
 VLC_API size_t vlc_fifo_GetCount(const vlc_fifo_t *) VLC_USED;
 
@@ -621,7 +624,7 @@ VLC_API size_t vlc_fifo_GetCount(const vlc_fifo_t *) VLC_USED;
  * @return the total number of bytes
  *
  * @note Zero bytes does not necessarily mean that the FIFO is empty since
- * a block could contain zero bytes. Use vlc_fifo_GetCount() to determine if
+ * a frame could contain zero bytes. Use vlc_fifo_GetCount() to determine if
  * a FIFO is empty.
  */
 VLC_API size_t vlc_fifo_GetBytes(const vlc_fifo_t *) VLC_USED;
@@ -641,4 +644,4 @@ static inline void vlc_fifo_Cleanup(void *fifo)
 
 /** @} */
 
-#endif /* VLC_BLOCK_H */
+#endif /* VLC_FRAME_H */
diff --git a/include/vlc_frame_helper.h b/include/vlc_frame_helper.h
new file mode 100644
index 0000000000..1602a430e4
--- /dev/null
+++ b/include/vlc_frame_helper.h
@@ -0,0 +1,369 @@
+/*****************************************************************************
+ * vlc_frame_helper.h: Helper functions for data blocks management.
+ *****************************************************************************
+ * Copyright (C) 2003-2017 VLC authors and VideoLAN
+ *
+ * Authors: Gildas Bazin <gbazin at netcourrier.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VLC_FRAME_HELPER_H
+#define VLC_FRAME_HELPER_H 1
+
+#include <vlc_frame.h>
+
+typedef struct vlc_frame_bytestream_t
+{
+    vlc_frame_t *p_chain;  /**< byte stream head block */
+    vlc_frame_t **pp_last; /**< tail ppointer for appends */
+    vlc_frame_t *p_data;  /**< byte stream read pointer data */
+    size_t   i_data_offset; /**< byte stream read pointer offset within block */
+    size_t   i_base_offset; /**< block base offset (previous blocks total size) */
+    size_t   i_total;  /**< total bytes over all linked blocks */
+} vlc_frame_bytestream_t;
+
+/*****************************************************************************
+ * vlc_frame_bytestream_t management
+ *****************************************************************************/
+static inline void vlc_frame_BytestreamInit( vlc_frame_bytestream_t *p_bytestream )
+{
+    p_bytestream->p_chain = p_bytestream->p_data = NULL;
+    p_bytestream->pp_last = &p_bytestream->p_chain;
+    p_bytestream->i_data_offset = 0;
+    p_bytestream->i_base_offset = 0;
+    p_bytestream->i_total = 0;
+}
+
+static inline void vlc_frame_BytestreamRelease( vlc_frame_bytestream_t *p_bytestream )
+{
+    vlc_frame_ChainRelease( p_bytestream->p_chain );
+}
+
+/**
+ * It flush all data (read and unread) from a vlc_frame_bytestream_t.
+ */
+static inline void vlc_frame_BytestreamEmpty( vlc_frame_bytestream_t *p_bytestream )
+{
+    vlc_frame_BytestreamRelease( p_bytestream );
+    vlc_frame_BytestreamInit( p_bytestream );
+}
+
+/**
+ * It flushes all already read data from a vlc_frame_bytestream_t.
+ */
+static inline void vlc_frame_BytestreamFlush( vlc_frame_bytestream_t *p_bytestream )
+{
+    vlc_frame_t *data = p_bytestream->p_chain;
+
+    while( data != p_bytestream->p_data )
+    {
+        vlc_frame_t *p_next = data->p_next;
+
+        p_bytestream->i_total -= data->i_buffer;
+        p_bytestream->i_base_offset -= data->i_buffer;
+        vlc_frame_Release( data );
+        data = p_next;
+    }
+
+    while( data != NULL && data->i_buffer == p_bytestream->i_data_offset )
+    {
+        vlc_frame_t *p_next = data->p_next;
+
+        p_bytestream->i_total -= data->i_buffer;
+        vlc_frame_Release( data );
+        data = p_next;
+        p_bytestream->i_data_offset = 0;
+    }
+
+    p_bytestream->p_chain = p_bytestream->p_data = data;
+    if( p_bytestream->p_chain == NULL )
+        p_bytestream->pp_last = &p_bytestream->p_chain;
+}
+
+static inline void vlc_frame_BytestreamPush( vlc_frame_bytestream_t *p_bytestream,
+                                         vlc_frame_t *p_data )
+{
+    vlc_frame_ChainLastAppend( &p_bytestream->pp_last, p_data );
+    if( !p_bytestream->p_data ) p_bytestream->p_data = p_data;
+    for( ; p_data; p_data = p_data->p_next )
+        p_bytestream->i_total += p_data->i_buffer;
+}
+
+static inline size_t vlc_frame_BytestreamRemaining( const vlc_frame_bytestream_t *p_bytestream )
+{
+    return ( p_bytestream->i_total > p_bytestream->i_base_offset + p_bytestream->i_data_offset ) ?
+             p_bytestream->i_total - p_bytestream->i_base_offset - p_bytestream->i_data_offset : 0;
+}
+
+VLC_USED
+static inline vlc_frame_t *vlc_frame_BytestreamPop( vlc_frame_bytestream_t *p_bytestream )
+{
+    vlc_frame_t *p_data;
+
+    vlc_frame_BytestreamFlush( p_bytestream );
+
+    p_data = p_bytestream->p_data;
+    if( unlikely( p_data == NULL ) )
+    {
+        return NULL;
+    }
+    else if( !p_data->p_next )
+    {
+        p_data->p_buffer += p_bytestream->i_data_offset;
+        p_data->i_buffer -= p_bytestream->i_data_offset;
+        p_bytestream->i_data_offset = 0;
+        p_bytestream->i_total = 0;
+        p_bytestream->p_chain = p_bytestream->p_data = NULL;
+        p_bytestream->pp_last = &p_bytestream->p_chain;
+        return p_data;
+    }
+
+    while( p_data->p_next && p_data->p_next->p_next )
+        p_data = p_data->p_next;
+
+    vlc_frame_t *p_data_old = p_data;
+    p_data = p_data->p_next;
+    p_data_old->p_next = NULL;
+    p_bytestream->pp_last = &p_data_old->p_next;
+    if( p_data )
+        p_bytestream->i_total -= p_data->i_buffer;
+
+    return p_data;
+}
+
+static inline int vlc_frame_WaitBytes( vlc_frame_bytestream_t *p_bytestream,
+                                   size_t i_data )
+{
+    if( vlc_frame_BytestreamRemaining( p_bytestream ) >= i_data )
+        return VLC_SUCCESS;
+    return VLC_EGENERIC;
+}
+
+static inline int vlc_frame_PeekBytes( vlc_frame_bytestream_t *p_bytestream,
+                                   uint8_t *p_data, size_t i_data )
+{
+    if( vlc_frame_BytestreamRemaining( p_bytestream ) < i_data )
+        return VLC_EGENERIC;
+
+    /* Copy the data */
+    size_t i_offset = p_bytestream->i_data_offset;
+    size_t i_size = i_data;
+    for( vlc_frame_t *p_frame = p_bytestream->p_data;
+         p_frame != NULL; p_frame = p_frame->p_next )
+    {
+        size_t i_copy = __MIN( i_size, p_frame->i_buffer - i_offset );
+        i_size -= i_copy;
+
+        if( i_copy )
+        {
+            memcpy( p_data, p_frame->p_buffer + i_offset, i_copy );
+            p_data += i_copy;
+        }
+
+        i_offset = 0;
+
+        if( !i_size ) break;
+    }
+
+    return VLC_SUCCESS;
+}
+
+static inline int vlc_frame_GetBytes( vlc_frame_bytestream_t *p_bytestream,
+                                  uint8_t *p_data, size_t i_data )
+{
+    if( vlc_frame_BytestreamRemaining( p_bytestream ) < i_data )
+        return VLC_EGENERIC;
+
+    /* Copy the data */
+    size_t i_offset = p_bytestream->i_data_offset;
+    size_t i_size = i_data;
+    size_t i_copy = 0;
+    vlc_frame_t *p_frame;
+    for( p_frame = p_bytestream->p_data;
+         p_frame != NULL; p_frame = p_frame->p_next )
+    {
+        i_copy = __MIN( i_size, p_frame->i_buffer - i_offset );
+        i_size -= i_copy;
+
+        if( i_copy && p_data != NULL )
+        {
+            memcpy( p_data, p_frame->p_buffer + i_offset, i_copy );
+            p_data += i_copy;
+        }
+
+        if( i_size == 0 )
+            break;
+
+        p_bytestream->i_base_offset += p_frame->i_buffer;
+        i_offset = 0;
+    }
+
+    p_bytestream->p_data = p_frame;
+    p_bytestream->i_data_offset = i_offset + i_copy;
+
+    return VLC_SUCCESS;
+}
+
+static inline int vlc_frame_SkipBytes( vlc_frame_bytestream_t *p_bytestream,
+                                   size_t i_data )
+{
+    return vlc_frame_GetBytes( p_bytestream, NULL, i_data );
+}
+
+static inline int vlc_frame_SkipByte( vlc_frame_bytestream_t *p_bytestream )
+{
+    return vlc_frame_GetBytes( p_bytestream, NULL, 1 );
+}
+
+static inline int vlc_frame_PeekOffsetBytes( vlc_frame_bytestream_t *p_bytestream,
+    size_t i_peek_offset, uint8_t *p_data, size_t i_data )
+{
+    const size_t i_remain = vlc_frame_BytestreamRemaining( p_bytestream );
+    if( i_remain < i_data + i_peek_offset )
+        return VLC_EGENERIC;
+
+    /* Find the right place */
+    size_t i_offset = p_bytestream->i_data_offset;
+    size_t i_size = i_peek_offset;
+    size_t i_copy = 0;
+    vlc_frame_t *p_frame;
+    for( p_frame = p_bytestream->p_data;
+         p_frame != NULL; p_frame = p_frame->p_next )
+    {
+        i_copy = __MIN( i_size, p_frame->i_buffer - i_offset );
+        i_size -= i_copy;
+
+        if( !i_size ) break;
+
+        i_offset = 0;
+    }
+
+    /* Copy the data */
+    i_offset += i_copy;
+    i_size = i_data;
+    for( ; p_frame != NULL; p_frame = p_frame->p_next )
+    {
+        i_copy = __MIN( i_size, p_frame->i_buffer - i_offset );
+        i_size -= i_copy;
+
+        if( i_copy )
+        {
+            memcpy( p_data, p_frame->p_buffer + i_offset, i_copy );
+            p_data += i_copy;
+        }
+
+        i_offset = 0;
+
+        if( !i_size ) break;
+    }
+
+    return VLC_SUCCESS;
+}
+
+typedef const uint8_t * (*vlc_frame_startcode_helper_t)( const uint8_t *, const uint8_t * );
+typedef bool (*vlc_frame_startcode_matcher_t)( uint8_t, size_t, const uint8_t * );
+
+static inline int vlc_frame_FindStartcodeFromOffset(
+    vlc_frame_bytestream_t *p_bytestream, size_t *pi_offset,
+    const uint8_t *p_startcode, int i_startcode_length,
+    vlc_frame_startcode_helper_t p_startcode_helper,
+    vlc_frame_startcode_matcher_t p_startcode_matcher )
+{
+    vlc_frame_t *p_data, *p_data_backup = 0;
+    ssize_t i_size = 0;
+    size_t i_offset, i_offset_backup = 0;
+    int i_caller_offset_backup = 0, i_match;
+
+    /* Find the right place */
+    i_size = *pi_offset + p_bytestream->i_data_offset;
+    for( p_data = p_bytestream->p_data;
+         p_data != NULL; p_data = p_data->p_next )
+    {
+        i_size -= p_data->i_buffer;
+        if( i_size < 0 ) break;
+    }
+
+    if( unlikely( i_size >= 0 ) )
+    {
+        /* Not enough data, bail out */
+        return VLC_EGENERIC;
+    }
+
+    /* Begin the search.
+     * We first look for an occurrence of the 1st startcode byte and
+     * if found, we do a more thorough check. */
+    i_size += p_data->i_buffer;
+    *pi_offset -= i_size;
+    i_match = 0;
+    for( ; p_data != NULL; p_data = p_data->p_next )
+    {
+        for( i_offset = i_size; i_offset < p_data->i_buffer; i_offset++ )
+        {
+            /* Use optimized helper when possible */
+            if( p_startcode_helper && !i_match &&
+               (p_data->i_buffer - i_offset) > ((size_t)i_startcode_length - 1) )
+            {
+                const uint8_t *p_res = p_startcode_helper( &p_data->p_buffer[i_offset],
+                                                           &p_data->p_buffer[p_data->i_buffer] );
+                if( p_res )
+                {
+                    *pi_offset += i_offset + (p_res - &p_data->p_buffer[i_offset]);
+                    return VLC_SUCCESS;
+                }
+                /* Then parsing boundary with legacy code */
+                i_offset = p_data->i_buffer - (i_startcode_length - 1);
+            }
+
+            bool b_matched = ( p_startcode_matcher )
+                           ? p_startcode_matcher( p_data->p_buffer[i_offset], i_match, p_startcode )
+                           : p_data->p_buffer[i_offset] == p_startcode[i_match];
+            if( b_matched )
+            {
+                if( i_match == 0 )
+                {
+                    p_data_backup = p_data;
+                    i_offset_backup = i_offset;
+                    i_caller_offset_backup = *pi_offset;
+                }
+
+                if( i_match + 1 == i_startcode_length )
+                {
+                    /* We have it */
+                    *pi_offset += i_offset - i_match;
+                    return VLC_SUCCESS;
+                }
+
+                i_match++;
+            }
+            else if ( i_match > 0 )
+            {
+                /* False positive */
+                p_data = p_data_backup;
+                i_offset = i_offset_backup;
+                *pi_offset = i_caller_offset_backup;
+                i_match = 0;
+            }
+
+        }
+        i_size = 0;
+        *pi_offset += i_offset;
+    }
+
+    *pi_offset -= i_match;
+    return VLC_EGENERIC;
+}
+
+#endif /* vlc_frame_HELPER_H */
diff --git a/include/vlc_httpd.h b/include/vlc_httpd.h
index 0b8f8c26bd..c710381b82 100644
--- a/include/vlc_httpd.h
+++ b/include/vlc_httpd.h
@@ -140,7 +140,7 @@ typedef struct httpd_stream_t httpd_stream_t;
 VLC_API httpd_stream_t * httpd_StreamNew( httpd_host_t *, const char *psz_url, const char *psz_mime, const char *psz_user, const char *psz_password ) VLC_USED;
 VLC_API void httpd_StreamDelete( httpd_stream_t * );
 VLC_API int httpd_StreamHeader( httpd_stream_t *, uint8_t *p_data, int i_data );
-VLC_API int httpd_StreamSend( httpd_stream_t *, const block_t *p_block );
+VLC_API int httpd_StreamSend( httpd_stream_t *, const vlc_frame_t *p_block );
 VLC_API int httpd_StreamSetHTTPHeaders(httpd_stream_t *, const httpd_header *, size_t);
 
 /* Msg functions facilities */
diff --git a/include/vlc_image.h b/include/vlc_image.h
index 250974f368..fb14eb22d8 100644
--- a/include/vlc_image.h
+++ b/include/vlc_image.h
@@ -23,6 +23,7 @@
 #ifndef VLC_IMAGE_H
 #define VLC_IMAGE_H 1
 
+#include <vlc_frame.h>
 # include <vlc_picture.h>
 # include <vlc_picture_fifo.h>
 
@@ -37,12 +38,12 @@ extern "C" {
 
 struct image_handler_t
 {
-    picture_t * (*pf_read)      ( image_handler_t *, block_t *,
+    picture_t * (*pf_read)      ( image_handler_t *, vlc_frame_t *,
                                   const es_format_t *,
                                   video_format_t * );
     picture_t * (*pf_read_url)  ( image_handler_t *, const char *,
                                   video_format_t * );
-    block_t * (*pf_write)       ( image_handler_t *, picture_t *,
+    vlc_frame_t * (*pf_write)       ( image_handler_t *, picture_t *,
                                   const video_format_t *, const video_format_t * );
     int (*pf_write_url)         ( image_handler_t *, picture_t *,
                                   const video_format_t *, const video_format_t *,
diff --git a/include/vlc_input.h b/include/vlc_input.h
index e6bd8440e3..fd41a69e4c 100644
--- a/include/vlc_input.h
+++ b/include/vlc_input.h
@@ -742,7 +742,7 @@ static inline int input_ModifyPcrSystem( input_thread_t *p_input, bool b_absolut
 /* */
 VLC_API decoder_t * input_DecoderCreate( vlc_object_t *, const es_format_t *, input_resource_t * ) VLC_USED;
 VLC_API void input_DecoderDelete( decoder_t * );
-VLC_API void input_DecoderDecode( decoder_t *, block_t *, bool b_do_pace );
+VLC_API void input_DecoderDecode( decoder_t *, vlc_frame_t *, bool b_do_pace );
 VLC_API void input_DecoderDrain( decoder_t * );
 VLC_API void input_DecoderFlush( decoder_t * );
 VLC_API int  input_DecoderSetSpuHighlight( decoder_t *, const vlc_spu_highlight_t * );
diff --git a/include/vlc_picture.h b/include/vlc_picture.h
index 58aba49445..0420da851e 100644
--- a/include/vlc_picture.h
+++ b/include/vlc_picture.h
@@ -41,6 +41,7 @@ using std::memory_order_release;
  */
 
 #include <vlc_es.h>
+#include <vlc_frame.h>
 
 /** Description of a planar graphic field */
 typedef struct plane_t
@@ -263,7 +264,7 @@ VLC_API picture_t *picture_Clone(picture_t *pic);
  *  - if strictly higher than 0, it will override the dimension.
  * If at most one of them is > 0 then the picture aspect ratio will be kept.
  */
-VLC_API int picture_Export( vlc_object_t *p_obj, block_t **pp_image, video_format_t *p_fmt, picture_t *p_picture, vlc_fourcc_t i_format, int i_override_width, int i_override_height );
+VLC_API int picture_Export( vlc_object_t *p_obj, vlc_frame_t **pp_image, video_format_t *p_fmt, picture_t *p_picture, vlc_fourcc_t i_format, int i_override_width, int i_override_height );
 
 /**
  * This function will setup all fields of a picture_t without allocating any
diff --git a/include/vlc_sout.h b/include/vlc_sout.h
index 484e91fff3..6311a61c37 100644
--- a/include/vlc_sout.h
+++ b/include/vlc_sout.h
@@ -33,6 +33,7 @@ extern "C" {
 
 #include <sys/types.h>
 #include <vlc_es.h>
+#include <vlc_frame.h>
 
 /**
  * \defgroup sout Stream output
@@ -75,8 +76,8 @@ struct sout_access_out_t
     char                    *psz_path;
     void                    *p_sys;
     int                     (*pf_seek)( sout_access_out_t *, off_t );
-    ssize_t                 (*pf_read)( sout_access_out_t *, block_t * );
-    ssize_t                 (*pf_write)( sout_access_out_t *, block_t * );
+    ssize_t                 (*pf_read)( sout_access_out_t *, vlc_frame_t * );
+    ssize_t                 (*pf_write)( sout_access_out_t *, vlc_frame_t * );
     int                     (*pf_control)( sout_access_out_t *, int, va_list );
 
     config_chain_t          *p_cfg;
@@ -93,8 +94,8 @@ VLC_API sout_access_out_t * sout_AccessOutNew( vlc_object_t *, const char *psz_a
         sout_AccessOutNew( VLC_OBJECT(obj), access, name )
 VLC_API void sout_AccessOutDelete( sout_access_out_t * );
 VLC_API int sout_AccessOutSeek( sout_access_out_t *, off_t );
-VLC_API ssize_t sout_AccessOutRead( sout_access_out_t *, block_t * );
-VLC_API ssize_t sout_AccessOutWrite( sout_access_out_t *, block_t * );
+VLC_API ssize_t sout_AccessOutRead( sout_access_out_t *, vlc_frame_t * );
+VLC_API ssize_t sout_AccessOutWrite( sout_access_out_t *, vlc_frame_t * );
 VLC_API int sout_AccessOutControl( sout_access_out_t *, int, ... );
 
 static inline bool sout_AccessOutCanControlPace( sout_access_out_t *p_ao )
@@ -158,7 +159,7 @@ enum sout_mux_query_e
 struct sout_input_t
 {
     const es_format_t *p_fmt;
-    block_fifo_t      *p_fifo;
+    vlc_frame_fifo_t      *p_fifo;
     void              *p_sys;
     es_format_t        fmt;
 };
@@ -168,7 +169,7 @@ VLC_API sout_mux_t * sout_MuxNew( sout_instance_t*, const char *, sout_access_ou
 VLC_API sout_input_t *sout_MuxAddStream( sout_mux_t *, const es_format_t * ) VLC_USED;
 VLC_API void sout_MuxDeleteStream( sout_mux_t *, sout_input_t * );
 VLC_API void sout_MuxDelete( sout_mux_t * );
-VLC_API int sout_MuxSendBuffer( sout_mux_t *, sout_input_t  *, block_t * );
+VLC_API int sout_MuxSendBuffer( sout_mux_t *, sout_input_t  *, vlc_frame_t * );
 VLC_API int sout_MuxGetStream(sout_mux_t *, unsigned, vlc_tick_t *);
 VLC_API void sout_MuxFlush( sout_mux_t *, sout_input_t * );
 
@@ -206,7 +207,7 @@ struct sout_stream_t
     void             *(*pf_add)( sout_stream_t *, const es_format_t * );
     void              (*pf_del)( sout_stream_t *, void * );
     /* manage a packet */
-    int               (*pf_send)( sout_stream_t *, void *, block_t* );
+    int               (*pf_send)( sout_stream_t *, void *, vlc_frame_t* );
     int               (*pf_control)( sout_stream_t *, int, va_list );
     void              (*pf_flush)( sout_stream_t *, void * );
 
@@ -231,9 +232,9 @@ static inline void sout_StreamIdDel( sout_stream_t *s,
 }
 
 static inline int sout_StreamIdSend( sout_stream_t *s,
-                                     void *id, block_t *b )
+                                     void *id, vlc_frame_t *f )
 {
-    return s->pf_send( s, id, b );
+    return s->pf_send( s, id, f );
 }
 
 static inline void sout_StreamFlush( sout_stream_t *s,
diff --git a/include/vlc_stream.h b/include/vlc_stream.h
index bc6c0d30b7..20f55d6a5d 100644
--- a/include/vlc_stream.h
+++ b/include/vlc_stream.h
@@ -23,7 +23,8 @@
 #ifndef VLC_STREAM_H
 #define VLC_STREAM_H 1
 
-#include <vlc_block.h>
+#include <vlc_data.h>
+#include <vlc_frame.h>
 
 # ifdef __cplusplus
 extern "C" {
@@ -108,7 +109,7 @@ struct stream_t
      * \return a data block,
      * NULL if no data available yet, on error and at end-of-stream
      */
-    block_t    *(*pf_block)(stream_t *, bool *eof);
+    vlc_data_t    *(*pf_block)(stream_t *, bool *eof);
 
     /**
      * Read directory.
@@ -167,7 +168,7 @@ enum stream_query_e
     STREAM_GET_META,        /**< arg1= vlc_meta_t *       res=can fail */
     STREAM_GET_CONTENT_TYPE,    /**< arg1= char **         res=can fail */
     STREAM_GET_SIGNAL,      /**< arg1=double *pf_quality, arg2=double *pf_strength   res=can fail */
-    STREAM_GET_TAGS,        /**< arg1=const block_t ** res=can fail */
+    STREAM_GET_TAGS,        /**< arg1=const vlc_data_t ** res=can fail */
 
     STREAM_SET_PAUSE_STATE = 0x200, /**< arg1= bool        res=can fail */
     STREAM_SET_TITLE,       /**< arg1= int          res=can fail */
@@ -218,7 +219,7 @@ VLC_USED;
  *
  * This function buffers for the requested number of bytes, waiting if
  * necessary. Then it stores a pointer to the buffer. Unlike vlc_stream_Read()
- * or vlc_stream_Block(), this function does not modify the stream read offset.
+ * or vlc_stream_Frame(), this function does not modify the stream read offset.
  *
  * \note
  * The buffer remains valid until the next read/peek or seek operation on the
@@ -247,7 +248,7 @@ VLC_API ssize_t vlc_stream_Peek(stream_t *, const uint8_t **, size_t) VLC_USED;
  *
  * \return either a data block or NULL
  */
-VLC_API block_t *vlc_stream_ReadBlock(stream_t *) VLC_USED;
+VLC_API vlc_data_t *vlc_stream_ReadBlock(stream_t *) VLC_USED;
 
 /**
  * Tells the current stream position.
@@ -309,7 +310,9 @@ static inline int vlc_stream_Control(stream_t *s, int query, ...)
     return ret;
 }
 
-VLC_API block_t *vlc_stream_Block(stream_t *s, size_t);
+VLC_API vlc_frame_t *vlc_stream_Frame(stream_t *s, size_t);
+VLC_API vlc_data_t *vlc_stream_Data(stream_t *s, size_t);
+
 VLC_API char *vlc_stream_ReadLine(stream_t *);
 
 /**
@@ -458,17 +461,17 @@ VLC_API vlc_stream_fifo_t *vlc_stream_fifo_New(vlc_object_t *parent,
                                                stream_t **reader);
 
 /**
- * Writes a block to a FIFO stream.
+ * Writes a data block to a FIFO stream.
  *
  * \param s FIFO stream created by vlc_stream_fifo_New()
- * \param block data block to write to the stream
+ * \param data data block to write to the stream
  * \return 0 on success. -1 if the reader end has already been closed
  * (errno is then set to EPIPE, and the block is deleted).
  *
  * \bug No congestion control is performed. If the reader end is not keeping
  * up with the writer end, buffers will accumulate in memory.
  */
-VLC_API int vlc_stream_fifo_Queue(vlc_stream_fifo_t *s, block_t *block);
+VLC_API int vlc_stream_fifo_Queue(vlc_stream_fifo_t *s, vlc_data_t *data);
 
 /**
  * Writes data to a FIFO stream.
diff --git a/include/vlc_stream_extractor.h b/include/vlc_stream_extractor.h
index 1090c70cd7..22d5c9845d 100644
--- a/include/vlc_stream_extractor.h
+++ b/include/vlc_stream_extractor.h
@@ -58,10 +58,10 @@ typedef struct stream_extractor_t {
      *
      * @{
      **/
-    ssize_t  (*pf_read)(struct stream_extractor_t*, void* buf, size_t len);
-    block_t* (*pf_block)(struct stream_extractor_t*, bool* eof);
-    int      (*pf_seek)(struct stream_extractor_t*, uint64_t);
-    int      (*pf_control)(struct stream_extractor_t*, int request, va_list args);
+    ssize_t (*pf_read)(struct stream_extractor_t*, void* buf, size_t len);
+    vlc_data_t* (*pf_block)(struct stream_extractor_t*, bool* eof);
+    int (*pf_seek)(struct stream_extractor_t*, uint64_t);
+    int (*pf_control)(struct stream_extractor_t*, int request, va_list args);
     /** @} */
 
     char const* identifier; /**< the name of the entity to be extracted */
diff --git a/include/vlc_threads.h b/include/vlc_threads.h
index 315729a097..a21d5f224a 100644
--- a/include/vlc_threads.h
+++ b/include/vlc_threads.h
@@ -42,7 +42,7 @@
  * This has no effects if thread cancellation is disabled.
  * This can be called when there is a rather slow non-sleeping operation.
  * This is also used to force a cancellation point in a function that would
- * otherwise <em>not always</em> be one (block_FifoGet() is an example).
+ * otherwise <em>not always</em> be one (vlc_frame_FifoGet() is an example).
  */
 VLC_API void vlc_testcancel(void);
 
diff --git a/include/vlc_vout.h b/include/vlc_vout.h
index 88f825d3fa..e32e3c1d25 100644
--- a/include/vlc_vout.h
+++ b/include/vlc_vout.h
@@ -100,7 +100,7 @@ VLC_API void vout_Close(vout_thread_t *vout);
  *
  */
 VLC_API int vout_GetSnapshot( vout_thread_t *p_vout,
-                              block_t **pp_image, picture_t **pp_picture,
+                              vlc_frame_t **pp_image, picture_t **pp_picture,
                               video_format_t *p_fmt,
                               const char *psz_format, vlc_tick_t i_timeout );
 
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 5a1ef31f25..96dfee6f43 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -4,8 +4,6 @@ include/vlc_actions.h
 include/vlc_aout.h
 include/vlc_arrays.h
 include/vlc_bits.h
-include/vlc_block.h
-include/vlc_block_helper.h
 include/vlc_charset.h
 include/vlc_codec.h
 include/vlc_codecs.h
@@ -13,6 +11,8 @@ include/vlc_common.h
 include/vlc_config.h
 include/vlc_config_cat.h
 include/vlc_configuration.h
+include/vlc_data.h
+include/vlc_data_helper.h
 include/vlc_demux.h
 include/vlc/deprecated.h
 include/vlc_epg.h
@@ -21,6 +21,8 @@ include/vlc_es_out.h
 include/vlc_events.h
 include/vlc_filter.h
 include/vlc_fixups.h
+include/vlc_frame.h
+include/vlc_frame_helper.h
 include/vlc_gcrypt.h
 include/vlc_httpd.h
 include/vlc_image.h
@@ -93,12 +95,13 @@ src/libvlc.c
 src/libvlc.h
 src/libvlc-module.c
 src/misc/actions.c
-src/misc/block.c
 src/misc/cpu.c
+src/misc/data.c
 src/misc/error.c
 src/misc/es_format.c
 src/misc/events.c
 src/misc/filter_chain.c
+src/misc/frame.c
 src/misc/image.c
 src/misc/md5.c
 src/misc/messages.c
diff --git a/src/Makefile.am b/src/Makefile.am
index e243f6473d..cceee21bfe 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -31,8 +31,9 @@ pluginsinclude_HEADERS = \
 	../include/vlc_atomic.h \
 	../include/vlc_avcodec.h \
 	../include/vlc_bits.h \
-	../include/vlc_block.h \
-	../include/vlc_block_helper.h \
+	../include/vlc_frame.h \
+	../include/vlc_frame_helper.h \
+	../include/vlc_data.h \
 	../include/vlc_boxes.h \
 	../include/vlc_charset.h \
 	../include/vlc_codec.h \
@@ -358,7 +359,8 @@ libvlccore_la_SOURCES = \
 	misc/probe.c \
 	misc/rand.c \
 	misc/mtime.c \
-	misc/block.c \
+	misc/frame.c \
+	misc/data.c \
 	misc/fifo.c \
 	misc/fourcc.c \
 	misc/fourcc_list.h \
diff --git a/src/audio_output/aout_internal.h b/src/audio_output/aout_internal.h
index 12fa4dfad9..49945548f6 100644
--- a/src/audio_output/aout_internal.h
+++ b/src/audio_output/aout_internal.h
@@ -108,7 +108,7 @@ aout_volume_t *aout_volume_New(vlc_object_t *, const audio_replay_gain_t *);
 #define aout_volume_New(o, g) aout_volume_New(VLC_OBJECT(o), g)
 int aout_volume_SetFormat(aout_volume_t *, vlc_fourcc_t);
 void aout_volume_SetVolume(aout_volume_t *, float);
-int aout_volume_Amplify(aout_volume_t *, block_t *);
+int aout_volume_Amplify(aout_volume_t *, vlc_frame_t *);
 void aout_volume_Delete(aout_volume_t *);
 
 
@@ -137,7 +137,7 @@ void aout_FormatsPrint(vlc_object_t *, const char *,
 int aout_DecNew(audio_output_t *, const audio_sample_format_t *,
                 struct vlc_clock_t *clock, const audio_replay_gain_t *);
 void aout_DecDelete(audio_output_t *);
-int aout_DecPlay(audio_output_t *aout, block_t *block);
+int aout_DecPlay(audio_output_t *aout, vlc_frame_t *frame);
 void aout_DecGetResetStats(audio_output_t *, unsigned *, unsigned *);
 void aout_DecChangePause(audio_output_t *, bool b_paused, vlc_tick_t i_date);
 void aout_DecChangeRate(audio_output_t *aout, float rate);
diff --git a/src/audio_output/dec.c b/src/audio_output/dec.c
index 91f9ccf2fe..6cfd894106 100644
--- a/src/audio_output/dec.c
+++ b/src/audio_output/dec.c
@@ -229,23 +229,23 @@ static void aout_DecSilence (audio_output_t *aout, vlc_tick_t length, vlc_tick_t
     const audio_sample_format_t *fmt = &owner->mixer_format;
     size_t frames = samples_from_vlc_tick(length, fmt->i_rate);
 
-    block_t *block = block_Alloc (frames * fmt->i_bytes_per_frame
+    vlc_frame_t *frame = vlc_frame_Alloc (frames * fmt->i_bytes_per_frame
                                   / fmt->i_frame_length);
-    if (unlikely(block == NULL))
+    if (unlikely(frame == NULL))
         return; /* uho! */
 
     msg_Dbg (aout, "inserting %zu zeroes", frames);
-    memset (block->p_buffer, 0, block->i_buffer);
-    block->i_nb_samples = frames;
-    block->i_pts = pts;
-    block->i_dts = pts;
-    block->i_length = length;
+    memset (frame->p_buffer, 0, frame->i_buffer);
+    frame->i_nb_samples = frames;
+    frame->i_pts = pts;
+    frame->i_dts = pts;
+    frame->i_length = length;
 
     const vlc_tick_t system_now = vlc_tick_now();
     const vlc_tick_t system_pts =
        vlc_clock_ConvertToSystem(owner->sync.clock, system_now, pts,
                                  owner->sync.rate);
-    aout->play(aout, block, system_pts);
+    aout->play(aout, frame, system_pts);
 }
 
 static void aout_DecSynchronize(audio_output_t *aout, vlc_tick_t system_now,
@@ -396,20 +396,20 @@ void aout_RequestRetiming(audio_output_t *aout, vlc_tick_t system_ts,
 /*****************************************************************************
  * aout_DecPlay : filter & mix the decoded buffer
  *****************************************************************************/
-int aout_DecPlay(audio_output_t *aout, block_t *block)
+int aout_DecPlay(audio_output_t *aout, vlc_frame_t *frame)
 {
     aout_owner_t *owner = aout_owner (aout);
 
-    assert (block->i_pts != VLC_TICK_INVALID);
+    assert (frame->i_pts != VLC_TICK_INVALID);
 
-    block->i_length = vlc_tick_from_samples( block->i_nb_samples,
+    frame->i_length = vlc_tick_from_samples( frame->i_nb_samples,
                                    owner->input_format.i_rate );
 
     int ret = aout_CheckReady (aout);
     if (unlikely(ret == AOUT_DEC_FAILED))
         goto drop; /* Pipeline is unrecoverably broken :-( */
 
-    if (block->i_flags & BLOCK_FLAG_DISCONTINUITY)
+    if (frame->i_flags & FRAME_FLAG_DISCONTINUITY)
     {
         owner->sync.discontinuity = true;
         owner->original_pts = VLC_TICK_INVALID;
@@ -429,18 +429,18 @@ int aout_DecPlay(audio_output_t *aout, block_t *block)
          * aout module. This PTS need to be saved here in order to use the PTS
          * of the first block that has been filtered. Indeed, aout filters may
          * need more than one block to output a new one. */
-        owner->original_pts = block->i_pts;
+        owner->original_pts = frame->i_pts;
     }
 
-    block = aout_FiltersPlay(owner->filters, block, owner->sync.rate);
-    if (block == NULL)
+    frame = aout_FiltersPlay(owner->filters, frame, owner->sync.rate);
+    if (frame == NULL)
         return ret;
 
     const vlc_tick_t original_pts = owner->original_pts;
     owner->original_pts = VLC_TICK_INVALID;
 
     /* Software volume */
-    aout_volume_Amplify (owner->volume, block);
+    aout_volume_Amplify (owner->volume, frame);
 
     /* Update delay */
     if (owner->sync.request_delay != owner->sync.delay)
@@ -449,7 +449,7 @@ int aout_DecPlay(audio_output_t *aout, block_t *block)
         vlc_tick_t delta = vlc_clock_SetDelay(owner->sync.clock, owner->sync.delay);
         aout_FiltersSetClockDelay(owner->filters, owner->sync.delay);
         if (delta > 0)
-            aout_DecSilence (aout, delta, block->i_pts);
+            aout_DecSilence (aout, delta, frame->i_pts);
     }
 
     /* Drift correction */
@@ -461,14 +461,14 @@ int aout_DecPlay(audio_output_t *aout, block_t *block)
                                   owner->sync.rate);
     /* Output */
     owner->sync.discontinuity = false;
-    aout->play(aout, block, play_date);
+    aout->play(aout, frame, play_date);
 
     atomic_fetch_add_explicit(&owner->buffers_played, 1, memory_order_relaxed);
     return ret;
 drop:
     owner->sync.discontinuity = true;
     owner->original_pts = VLC_TICK_INVALID;
-    block_Release (block);
+    vlc_frame_Release (frame);
     atomic_fetch_add_explicit(&owner->buffers_lost, 1, memory_order_relaxed);
     return ret;
 }
@@ -548,9 +548,9 @@ void aout_DecDrain(audio_output_t *aout)
     if (!owner->mixer_format.i_format)
         return;
 
-    block_t *block = aout_FiltersDrain (owner->filters);
-    if (block)
-        aout->play(aout, block, vlc_tick_now());
+    vlc_frame_t *frame = aout_FiltersDrain (owner->filters);
+    if (frame)
+        aout->play(aout, frame, vlc_tick_now());
 
     aout_Drain(aout);
 
diff --git a/src/audio_output/filters.c b/src/audio_output/filters.c
index 6a37c8e8ab..1526668b9f 100644
--- a/src/audio_output/filters.c
+++ b/src/audio_output/filters.c
@@ -275,49 +275,49 @@ error:
 /**
  * Filters an audio buffer through a chain of filters.
  */
-static block_t *aout_FiltersPipelinePlay(filter_t *const *filters,
-                                         unsigned count, block_t *block)
+static vlc_frame_t *aout_FiltersPipelinePlay(filter_t *const *filters,
+                                         unsigned count, vlc_frame_t *frame)
 {
     /* TODO: use filter chain */
-    for (unsigned i = 0; (i < count) && (block != NULL); i++)
+    for (unsigned i = 0; (i < count) && (frame != NULL); i++)
     {
         filter_t *filter = filters[i];
 
-        /* Please note that p_block->i_nb_samples & i_buffer
+        /* Please note that p_frame->i_nb_samples & i_buffer
          * shall be set by the filter plug-in. */
-        block = filter->pf_audio_filter (filter, block);
+        frame = filter->pf_audio_filter (filter, frame);
     }
-    return block;
+    return frame;
 }
 
 
 /**
  * Drain the chain of filters.
  */
-static block_t *aout_FiltersPipelineDrain(filter_t *const *filters,
+static vlc_frame_t *aout_FiltersPipelineDrain(filter_t *const *filters,
                                           unsigned count)
 {
-    block_t *chain = NULL;
+    vlc_frame_t *chain = NULL;
 
     for (unsigned i = 0; i < count; i++)
     {
         filter_t *filter = filters[i];
 
-        block_t *block = filter_DrainAudio (filter);
-        if (block)
+        vlc_frame_t *frame = filter_DrainAudio (filter);
+        if (frame)
         {
-            /* If there is a drained block, filter it through the following
+            /* If there is a drained frame, filter it through the following
              * chain of filters  */
             if (i + 1 < count)
-                block = aout_FiltersPipelinePlay (&filters[i + 1],
-                                                  count - i - 1, block);
-            if (block)
-                block_ChainAppend (&chain, block);
+                frame = aout_FiltersPipelinePlay (&filters[i + 1],
+                                                  count - i - 1, frame);
+            if (frame)
+                vlc_frame_ChainAppend (&chain, frame);
         }
     }
 
     if (chain)
-        return block_ChainGather(chain);
+        return vlc_frame_ChainGather(chain);
     else
         return NULL;
 }
@@ -716,7 +716,7 @@ bool aout_FiltersAdjustResampling (aout_filters_t *filters, int adjust)
     return filters->resampling != 0;
 }
 
-block_t *aout_FiltersPlay(aout_filters_t *filters, block_t *block, float rate)
+vlc_frame_t *aout_FiltersPlay(aout_filters_t *filters, vlc_frame_t *frame, float rate)
 {
     int nominal_rate = 0;
 
@@ -732,12 +732,12 @@ block_t *aout_FiltersPlay(aout_filters_t *filters, block_t *block, float rate)
         rate_filter->fmt_in.audio.i_rate = lroundf(nominal_rate * rate);
     }
 
-    block = aout_FiltersPipelinePlay (filters->tab, filters->count, block);
+    frame = aout_FiltersPipelinePlay (filters->tab, filters->count, frame);
     if (filters->resampler != NULL)
     {   /* NOTE: the resampler needs to run even if resampling is 0.
          * The decoder and output rates can still be different. */
         filters->resampler->fmt_in.audio.i_rate += filters->resampling;
-        block = aout_FiltersPipelinePlay (&filters->resampler, 1, block);
+        frame = aout_FiltersPipelinePlay (&filters->resampler, 1, frame);
         filters->resampler->fmt_in.audio.i_rate -= filters->resampling;
     }
 
@@ -746,43 +746,43 @@ block_t *aout_FiltersPlay(aout_filters_t *filters, block_t *block, float rate)
         assert (filters->rate_filter != NULL);
         filters->rate_filter->fmt_in.audio.i_rate = nominal_rate;
     }
-    return block;
+    return frame;
 
 drop:
-    block_Release (block);
+    vlc_frame_Release (frame);
     return NULL;
 }
 
-block_t *aout_FiltersDrain (aout_filters_t *filters)
+vlc_frame_t *aout_FiltersDrain (aout_filters_t *filters)
 {
     /* Drain the filters pipeline */
-    block_t *block = aout_FiltersPipelineDrain (filters->tab, filters->count);
+    vlc_frame_t *frame = aout_FiltersPipelineDrain (filters->tab, filters->count);
 
     if (filters->resampler != NULL)
     {
-        block_t *chain = NULL;
+        vlc_frame_t *chain = NULL;
 
         filters->resampler->fmt_in.audio.i_rate += filters->resampling;
 
-        if (block)
+        if (frame)
         {
-            /* Resample the drained block from the filters pipeline */
-            block = aout_FiltersPipelinePlay (&filters->resampler, 1, block);
-            if (block)
-                block_ChainAppend (&chain, block);
+            /* Resample the drained frame from the filters pipeline */
+            frame = aout_FiltersPipelinePlay (&filters->resampler, 1, frame);
+            if (frame)
+                vlc_frame_ChainAppend (&chain, frame);
         }
 
         /* Drain the resampler filter */
-        block = aout_FiltersPipelineDrain (&filters->resampler, 1);
-        if (block)
-            block_ChainAppend (&chain, block);
+        frame = aout_FiltersPipelineDrain (&filters->resampler, 1);
+        if (frame)
+            vlc_frame_ChainAppend (&chain, frame);
 
         filters->resampler->fmt_in.audio.i_rate -= filters->resampling;
 
-        return chain ? block_ChainGather (chain) : NULL;
+        return chain ? vlc_frame_ChainGather (chain) : NULL;
     }
     else
-        return block;
+        return frame;
 }
 
 void aout_FiltersFlush (aout_filters_t *filters)
diff --git a/src/audio_output/volume.c b/src/audio_output/volume.c
index b86bb1d36c..b0492c70fd 100644
--- a/src/audio_output/volume.c
+++ b/src/audio_output/volume.c
@@ -130,7 +130,7 @@ void aout_volume_SetVolume(aout_volume_t *vol, float factor)
 /**
  * Applies replay gain and software volume to an audio buffer.
  */
-int aout_volume_Amplify(aout_volume_t *vol, block_t *block)
+int aout_volume_Amplify(aout_volume_t *vol, vlc_frame_t *frame)
 {
     if (unlikely(vol == NULL) || vol->module == NULL)
         return -1;
@@ -138,7 +138,7 @@ int aout_volume_Amplify(aout_volume_t *vol, block_t *block)
     float amp = vol->output_factor
               * vlc_atomic_load_float (&vol->gain_factor);
 
-    vol->object.amplify(&vol->object, block, amp);
+    vol->object.amplify(&vol->object, frame, amp);
     return 0;
 }
 
diff --git a/src/check_symbols b/src/check_symbols
index 5b92baa335..8b429f49db 100755
--- a/src/check_symbols
+++ b/src/check_symbols
@@ -12,7 +12,7 @@ echo "Looking for unprefixed exported symbols..."
 cat libvlccore.sym | grep -v \
 	-e '^vlc_' -e '^vlm_' -e '^libvlc_[A-Z]' -e '^VLC_' \
 	-e '^input_' -e '^access_' -e '^demux_' -e '^decoder_' \
-	-e '^image_' -e '^block_' -e '^picture_' -e '^subpicture_' \
+	-e '^image_' -e '^picture_' -e '^subpicture_' \
 	-e '^es_format' -e '^[asv]out_' -e '^spu_' -e '^filter_' \
 	-e '^video_format_' \
 	-e '^playlist_' -e '^services_discovery_' -e '^intf_' \
diff --git a/src/input/access.c b/src/input/access.c
index eab763f020..fc524beb03 100644
--- a/src/input/access.c
+++ b/src/input/access.c
@@ -215,10 +215,10 @@ int access_vaDirectoryControlHelper( stream_t *p_access, int i_query, va_list ar
 }
 
 /* Block access */
-static block_t *AStreamReadBlock(stream_t *s, bool *restrict eof)
+static vlc_data_t *AStreamReadBlock(stream_t *s, bool *restrict eof)
 {
     stream_t *access = s->p_sys;
-    block_t * block;
+    vlc_data_t * block;
 
     if (vlc_stream_Eof(access))
     {
diff --git a/src/input/decoder.c b/src/input/decoder.c
index 36b5ac8f89..e968d27e3b 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -32,7 +32,7 @@
 #include <stdatomic.h>
 
 #include <vlc_common.h>
-#include <vlc_block.h>
+#include <vlc_frame.h>
 #include <vlc_vout.h>
 #include <vlc_aout.h>
 #include <vlc_sout.h>
@@ -92,7 +92,7 @@ struct decoder_owner
     atomic_int     reload;
 
     /* fifo */
-    block_fifo_t *p_fifo;
+    vlc_frame_fifo_t *p_fifo;
 
     /* Lock for communication with decoder thread */
     vlc_mutex_t lock;
@@ -152,7 +152,7 @@ struct decoder_owner
 
 /* */
 #define DECODER_SPU_VOUT_WAIT_DURATION   VLC_TICK_FROM_MS(200)
-#define BLOCK_FLAG_CORE_PRIVATE_RELOADED (1 << BLOCK_FLAG_CORE_PRIVATE_SHIFT)
+#define FRAME_FLAG_CORE_PRIVATE_RELOADED (1 << FRAME_FLAG_CORE_PRIVATE_SHIFT)
 
 static inline struct decoder_owner *dec_get_owner( decoder_t *p_dec )
 {
@@ -696,20 +696,20 @@ static float DecoderGetDisplayRate( decoder_t *p_dec )
 /*****************************************************************************
  * Public functions
  *****************************************************************************/
-block_t *decoder_NewAudioBuffer( decoder_t *dec, int samples )
+vlc_frame_t *decoder_NewAudioBuffer( decoder_t *dec, int samples )
 {
     assert( dec->fmt_out.audio.i_frame_length > 0
          && dec->fmt_out.audio.i_bytes_per_frame  > 0 );
 
     size_t length = samples * dec->fmt_out.audio.i_bytes_per_frame
                             / dec->fmt_out.audio.i_frame_length;
-    block_t *block = block_Alloc( length );
-    if( likely(block != NULL) )
+    vlc_frame_t *frame = vlc_frame_Alloc( length );
+    if( likely(frame != NULL) )
     {
-        block->i_nb_samples = samples;
-        block->i_pts = block->i_length = 0;
+        frame->i_nb_samples = samples;
+        frame->i_pts = frame->i_length = 0;
     }
-    return block;
+    return frame;
 }
 
 static void RequestReload( decoder_t * p_dec )
@@ -744,13 +744,13 @@ static void DecoderWaitUnblock( decoder_t *p_dec )
     }
 }
 
-static inline void DecoderUpdatePreroll( vlc_tick_t *pi_preroll, const block_t *p )
+static inline void DecoderUpdatePreroll( vlc_tick_t *pi_preroll, const vlc_frame_t *p )
 {
-    if( p->i_flags & BLOCK_FLAG_PREROLL )
+    if( p->i_flags & FRAME_FLAG_PREROLL )
         *pi_preroll = (vlc_tick_t)INT64_MAX;
     /* Check if we can use the packet for end of preroll */
-    else if( (p->i_flags & BLOCK_FLAG_DISCONTINUITY) &&
-             (p->i_buffer == 0 || (p->i_flags & BLOCK_FLAG_CORRUPTED)) )
+    else if( (p->i_flags & FRAME_FLAG_DISCONTINUITY) &&
+             (p->i_buffer == 0 || (p->i_flags & FRAME_FLAG_CORRUPTED)) )
         *pi_preroll = (vlc_tick_t)INT64_MAX;
     else if( p->i_dts != VLC_TICK_INVALID )
         *pi_preroll = __MIN( *pi_preroll, p->i_dts );
@@ -759,12 +759,12 @@ static inline void DecoderUpdatePreroll( vlc_tick_t *pi_preroll, const block_t *
 }
 
 #ifdef ENABLE_SOUT
-static int DecoderPlaySout( decoder_t *p_dec, block_t *p_sout_block )
+static int DecoderPlaySout( decoder_t *p_dec, vlc_frame_t *p_sout_frame )
 {
     struct decoder_owner *p_owner = dec_get_owner( p_dec );
 
     assert( p_owner->p_clock );
-    assert( !p_sout_block->p_next );
+    assert( !p_sout_frame->p_next );
 
     vlc_mutex_lock( &p_owner->lock );
 
@@ -779,19 +779,19 @@ static int DecoderPlaySout( decoder_t *p_dec, block_t *p_sout_block )
     vlc_mutex_unlock( &p_owner->lock );
 
     /* FIXME --VLC_TICK_INVALID inspect stream_output*/
-    return sout_InputSendBuffer( p_owner->p_sout_input, p_sout_block );
+    return sout_InputSendBuffer( p_owner->p_sout_input, p_sout_frame );
 }
 
-/* This function process a block for sout
+/* This function process a frame for sout
  */
-static void DecoderProcessSout( decoder_t *p_dec, block_t *p_block )
+static void DecoderProcessSout( decoder_t *p_dec, vlc_frame_t *p_frame )
 {
     struct decoder_owner *p_owner = dec_get_owner( p_dec );
-    block_t *p_sout_block;
-    block_t **pp_block = p_block ? &p_block : NULL;
+    vlc_frame_t *p_sout_frame;
+    vlc_frame_t **pp_frame = p_frame ? &p_frame : NULL;
 
-    while( ( p_sout_block =
-                 p_dec->pf_packetize( p_dec, pp_block ) ) )
+    while( ( p_sout_frame =
+                 p_dec->pf_packetize( p_dec, pp_frame ) ) )
     {
         if( p_owner->p_sout_input == NULL )
         {
@@ -817,19 +817,19 @@ static void DecoderProcessSout( decoder_t *p_dec, block_t *p_block )
                          (char *)&p_owner->fmt.i_codec );
                 p_owner->error = true;
 
-                if(p_block)
-                    block_Release(p_block);
+                if(p_frame)
+                    vlc_frame_Release(p_frame);
 
-                block_ChainRelease(p_sout_block);
+                vlc_frame_ChainRelease(p_sout_frame);
                 break;
             }
         }
 
-        while( p_sout_block )
+        while( p_sout_frame )
         {
-            block_t *p_next = p_sout_block->p_next;
+            vlc_frame_t *p_next = p_sout_frame->p_next;
 
-            p_sout_block->p_next = NULL;
+            p_sout_frame->p_next = NULL;
 
             if( p_owner->p_sout->b_wants_substreams && p_dec->pf_get_cc )
             {
@@ -837,7 +837,7 @@ static void DecoderProcessSout( decoder_t *p_dec, block_t *p_block )
                     !p_owner->cc.b_sout_created )
                 {
                     decoder_cc_desc_t desc;
-                    block_t *p_cc = p_dec->pf_get_cc( p_dec, &desc );
+                    vlc_frame_t *p_cc = p_dec->pf_get_cc( p_dec, &desc );
                     if( p_cc )
                     {
                         if(!p_owner->cc.b_sout_created)
@@ -854,13 +854,13 @@ static void DecoderProcessSout( decoder_t *p_dec, block_t *p_block )
                         if( !p_owner->cc.p_sout_input ||
                             sout_InputSendBuffer( p_owner->cc.p_sout_input, p_cc ) )
                         {
-                            block_Release( p_cc );
+                            vlc_frame_Release( p_cc );
                         }
                     }
                 }
             }
 
-            if( DecoderPlaySout( p_dec, p_sout_block ) == VLC_EGENERIC )
+            if( DecoderPlaySout( p_dec, p_sout_frame ) == VLC_EGENERIC )
             {
                 msg_Err( p_dec, "cannot continue streaming due to errors with codec %4.4s",
                                 (char *)&p_owner->fmt.i_codec );
@@ -869,20 +869,20 @@ static void DecoderProcessSout( decoder_t *p_dec, block_t *p_block )
 
                 /* Cleanup */
 
-                if( p_block )
-                    block_Release( p_block );
+                if( p_frame )
+                    vlc_frame_Release( p_frame );
 
-                block_ChainRelease( p_next );
+                vlc_frame_ChainRelease( p_next );
                 return;
             }
 
-            p_sout_block = p_next;
+            p_sout_frame = p_next;
         }
     }
 }
 #endif
 
-static void DecoderPlayCc( decoder_t *p_dec, block_t *p_cc,
+static void DecoderPlayCc( decoder_t *p_dec, vlc_frame_t *p_cc,
                            const decoder_cc_desc_t *p_desc )
 {
     struct decoder_owner *p_owner = dec_get_owner( p_dec );
@@ -905,11 +905,11 @@ static void DecoderPlayCc( decoder_t *p_dec, block_t *p_cc,
 
         if( i_bitmap > 1 )
         {
-            block_FifoPut( p_ccowner->p_fifo, block_Duplicate(p_cc) );
+            vlc_frame_FifoPut( p_ccowner->p_fifo, vlc_frame_Duplicate(p_cc) );
         }
         else
         {
-            block_FifoPut( p_ccowner->p_fifo, p_cc );
+            vlc_frame_FifoPut( p_ccowner->p_fifo, p_cc );
             p_cc = NULL; /* was last dec */
         }
     }
@@ -917,13 +917,13 @@ static void DecoderPlayCc( decoder_t *p_dec, block_t *p_cc,
     vlc_mutex_unlock( &p_owner->lock );
 
     if( p_cc ) /* can have bitmap set but no created decs */
-        block_Release( p_cc );
+        vlc_frame_Release( p_cc );
 }
 
 static void PacketizerGetCc( decoder_t *p_dec, decoder_t *p_dec_cc )
 {
     struct decoder_owner *p_owner = dec_get_owner( p_dec );
-    block_t *p_cc;
+    vlc_frame_t *p_cc;
     decoder_cc_desc_t desc;
 
     /* Do not try retreiving CC if not wanted (sout) or cannot be retreived */
@@ -938,7 +938,7 @@ static void PacketizerGetCc( decoder_t *p_dec, decoder_t *p_dec_cc )
     DecoderPlayCc( p_dec, p_cc, &desc );
 }
 
-static void DecoderQueueCc( decoder_t *p_videodec, block_t *p_cc,
+static void DecoderQueueCc( decoder_t *p_videodec, vlc_frame_t *p_cc,
                            const decoder_cc_desc_t *p_desc )
 {
     struct decoder_owner *p_owner = dec_get_owner( p_videodec );
@@ -949,7 +949,7 @@ static void DecoderQueueCc( decoder_t *p_videodec, block_t *p_cc,
            ( !p_owner->p_packetizer || !p_owner->p_packetizer->pf_get_cc ) )
             DecoderPlayCc( p_videodec, p_cc, p_desc );
         else
-            block_Release( p_cc );
+            vlc_frame_Release( p_cc );
     }
 }
 
@@ -1118,7 +1118,7 @@ static void DecoderQueueThumbnail( decoder_t *p_dec, picture_t *p_pic )
 
 }
 
-static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
+static void DecoderPlayAudio( decoder_t *p_dec, vlc_frame_t *p_audio,
                              unsigned *restrict pi_lost_sum )
 {
     struct decoder_owner *p_owner = dec_get_owner( p_dec );
@@ -1130,7 +1130,7 @@ static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
     if( p_owner->i_preroll_end > p_audio->i_pts )
     {
         vlc_mutex_unlock( &p_owner->lock );
-        block_Release( p_audio );
+        vlc_frame_Release( p_audio );
         return;
     }
 
@@ -1151,7 +1151,7 @@ static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
     {
         msg_Warn( p_dec, "non-dated audio buffer received" );
         *pi_lost_sum += 1;
-        block_Release( p_audio );
+        vlc_frame_Release( p_audio );
         return;
     }
 
@@ -1189,7 +1189,7 @@ static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
     {
         msg_Dbg( p_dec, "discarded audio buffer" );
         *pi_lost_sum += 1;
-        block_Release( p_audio );
+        vlc_frame_Release( p_audio );
     }
     return;
 }
@@ -1225,7 +1225,7 @@ static void DecoderUpdateStatAudio( struct decoder_owner *p_owner,
     }
 }
 
-static void DecoderQueueAudio( decoder_t *p_dec, block_t *p_aout_buf )
+static void DecoderQueueAudio( decoder_t *p_dec, vlc_frame_t *p_aout_buf )
 {
     unsigned lost = 0;
     struct decoder_owner *p_owner = dec_get_owner( p_dec );
@@ -1299,12 +1299,12 @@ static void DecoderQueueSpu( decoder_t *p_dec, subpicture_t *p_spu )
     }
 }
 
-static void DecoderProcess( decoder_t *p_dec, block_t *p_block );
-static void DecoderDecode( decoder_t *p_dec, block_t *p_block )
+static void DecoderProcess( decoder_t *p_dec, vlc_frame_t *p_frame );
+static void DecoderDecode( decoder_t *p_dec, vlc_frame_t *p_frame )
 {
     struct decoder_owner *p_owner = dec_get_owner( p_dec );
 
-    int ret = p_dec->pf_decode( p_dec, p_block );
+    int ret = p_dec->pf_decode( p_dec, p_frame );
     switch( ret )
     {
         case VLCDEC_SUCCESS:
@@ -1315,15 +1315,15 @@ static void DecoderDecode( decoder_t *p_dec, block_t *p_block )
             break;
         case VLCDEC_RELOAD:
             RequestReload( p_dec );
-            if( unlikely( p_block == NULL ) )
+            if( unlikely( p_frame == NULL ) )
                 break;
-            if( !( p_block->i_flags & BLOCK_FLAG_CORE_PRIVATE_RELOADED ) )
+            if( !( p_frame->i_flags & FRAME_FLAG_CORE_PRIVATE_RELOADED ) )
             {
-                p_block->i_flags |= BLOCK_FLAG_CORE_PRIVATE_RELOADED;
-                DecoderProcess( p_dec, p_block );
+                p_frame->i_flags |= FRAME_FLAG_CORE_PRIVATE_RELOADED;
+                DecoderProcess( p_dec, p_frame );
             }
-            else /* We prefer loosing this block than an infinite recursion */
-                block_Release( p_block );
+            else /* We prefer loosing this frame than an infinite recursion */
+                vlc_frame_Release( p_frame );
             break;
         default:
             vlc_assert_unreachable();
@@ -1331,12 +1331,12 @@ static void DecoderDecode( decoder_t *p_dec, block_t *p_block )
 }
 
 /**
- * Decode a block
+ * Decode a frame
  *
  * \param p_dec the decoder object
- * \param p_block the block to decode
+ * \param p_frame the frame to decode
  */
-static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
+static void DecoderProcess( decoder_t *p_dec, vlc_frame_t *p_frame )
 {
     struct decoder_owner *p_owner = dec_get_owner( p_dec );
 
@@ -1346,7 +1346,7 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
     /* Here, the atomic doesn't prevent to miss a reload request.
      * DecoderProcess() can still be called after the decoder module or the
      * audio output requested a reload. This will only result in a drop of an
-     * input block or an output buffer. */
+     * input frame or an output buffer. */
     enum reload reload;
     if( ( reload = atomic_exchange( &p_owner->reload, RELOAD_NO_REQUEST ) ) )
     {
@@ -1358,17 +1358,17 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
     }
 
     bool packetize = p_owner->p_packetizer != NULL;
-    if( p_block )
+    if( p_frame )
     {
-        if( p_block->i_buffer <= 0 )
+        if( p_frame->i_buffer <= 0 )
             goto error;
 
         vlc_mutex_lock( &p_owner->lock );
-        DecoderUpdatePreroll( &p_owner->i_preroll_end, p_block );
+        DecoderUpdatePreroll( &p_owner->i_preroll_end, p_frame );
         vlc_mutex_unlock( &p_owner->lock );
-        if( unlikely( p_block->i_flags & BLOCK_FLAG_CORE_PRIVATE_RELOADED ) )
+        if( unlikely( p_frame->i_flags & FRAME_FLAG_CORE_PRIVATE_RELOADED ) )
         {
-            /* This block has already been packetized */
+            /* This frame has already been packetized */
             packetize = false;
         }
     }
@@ -1376,18 +1376,18 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
 #ifdef ENABLE_SOUT
     if( p_owner->p_sout != NULL )
     {
-        DecoderProcessSout( p_dec, p_block );
+        DecoderProcessSout( p_dec, p_frame );
         return;
     }
 #endif
     if( packetize )
     {
-        block_t *p_packetized_block;
-        block_t **pp_block = p_block ? &p_block : NULL;
+        vlc_frame_t *p_packetized_frame;
+        vlc_frame_t **pp_frame = p_frame ? &p_frame : NULL;
         decoder_t *p_packetizer = p_owner->p_packetizer;
 
-        while( (p_packetized_block =
-                p_packetizer->pf_packetize( p_packetizer, pp_block ) ) )
+        while( (p_packetized_frame =
+                p_packetizer->pf_packetize( p_packetizer, pp_frame ) ) )
         {
             if( !es_format_IsSimilar( &p_dec->fmt_in, &p_packetizer->fmt_out ) )
             {
@@ -1399,7 +1399,7 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
                 if( ReloadDecoder( p_dec, false, &p_packetizer->fmt_out,
                                    RELOAD_DECODER ) != VLC_SUCCESS )
                 {
-                    block_ChainRelease( p_packetized_block );
+                    vlc_frame_ChainRelease( p_packetized_frame );
                     return;
                 }
             }
@@ -1407,32 +1407,32 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
             if( p_packetizer->pf_get_cc )
                 PacketizerGetCc( p_dec, p_packetizer );
 
-            while( p_packetized_block )
+            while( p_packetized_frame )
             {
-                block_t *p_next = p_packetized_block->p_next;
-                p_packetized_block->p_next = NULL;
+                vlc_frame_t *p_next = p_packetized_frame->p_next;
+                p_packetized_frame->p_next = NULL;
 
-                DecoderDecode( p_dec, p_packetized_block );
+                DecoderDecode( p_dec, p_packetized_frame );
                 if( p_owner->error )
                 {
-                    block_ChainRelease( p_next );
+                    vlc_frame_ChainRelease( p_next );
                     return;
                 }
 
-                p_packetized_block = p_next;
+                p_packetized_frame = p_next;
             }
         }
         /* Drain the decoder after the packetizer is drained */
-        if( !pp_block )
+        if( !pp_frame )
             DecoderDecode( p_dec, NULL );
     }
     else
-        DecoderDecode( p_dec, p_block );
+        DecoderDecode( p_dec, p_frame );
     return;
 
 error:
-    if( p_block )
-        block_Release( p_block );
+    if( p_frame )
+        vlc_frame_Release( p_frame );
 }
 
 static void DecoderProcessFlush( decoder_t *p_dec )
@@ -1669,11 +1669,11 @@ static void *DecoderThread( void *p_data )
         vlc_cond_signal( &p_owner->wait_fifo );
         vlc_testcancel(); /* forced expedited cancellation in case of stop */
 
-        block_t *p_block = vlc_fifo_DequeueUnlocked( p_owner->p_fifo );
-        if( p_block == NULL )
+        vlc_frame_t *p_frame = vlc_frame_FifoDequeueUnlocked( p_owner->p_fifo );
+        if( p_frame == NULL )
         {
             if( likely(!p_owner->b_draining) )
-            {   /* Wait for a block to decode (or a request to drain) */
+            {   /* Wait for a frame to decode (or a request to drain) */
                 p_owner->b_idle = true;
                 vlc_cond_signal( &p_owner->wait_acknowledge );
                 vlc_fifo_Wait( p_owner->p_fifo );
@@ -1681,15 +1681,15 @@ static void *DecoderThread( void *p_data )
                 continue;
             }
             /* We have emptied the FIFO and there is a pending request to
-             * drain. Pass p_block = NULL to decoder just once. */
+             * drain. Pass p_frame = NULL to decoder just once. */
         }
 
         vlc_fifo_Unlock( p_owner->p_fifo );
 
         int canc = vlc_savecancel();
-        DecoderProcess( p_dec, p_block );
+        DecoderProcess( p_dec, p_frame );
 
-        if( p_block == NULL && p_dec->fmt_out.i_cat == AUDIO_ES )
+        if( p_frame == NULL && p_dec->fmt_out.i_cat == AUDIO_ES )
         {   /* Draining: the decoder is drained and all decoded buffers are
              * queued to the output at this point. Now drain the output. */
             if( p_owner->p_aout != NULL )
@@ -1700,7 +1700,7 @@ static void *DecoderThread( void *p_data )
         /* TODO? Wait for draining instead of polling. */
         vlc_mutex_lock( &p_owner->lock );
         vlc_fifo_Lock( p_owner->p_fifo );
-        if( p_owner->b_draining && (p_block == NULL) )
+        if( p_owner->b_draining && (p_frame == NULL) )
         {
             p_owner->b_draining = false;
             p_owner->drained = true;
@@ -1812,7 +1812,7 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
     es_format_Init( &p_owner->fmt, fmt->i_cat, 0 );
 
     /* decoder fifo */
-    p_owner->p_fifo = block_FifoNew();
+    p_owner->p_fifo = vlc_frame_FifoNew();
     if( unlikely(p_owner->p_fifo == NULL) )
     {
         vlc_object_delete(p_dec);
@@ -1920,7 +1920,7 @@ static void DeleteDecoder( decoder_t * p_dec )
     decoder_Clean( p_dec );
 
     /* Free all packets still in the decoder fifo. */
-    block_FifoRelease( p_owner->p_fifo );
+    vlc_frame_FifoRelease( p_owner->p_fifo );
 
     /* Cleanup */
 #ifdef ENABLE_SOUT
@@ -2149,13 +2149,13 @@ void input_DecoderDelete( decoder_t *p_dec )
 }
 
 /**
- * Put a block_t in the decoder's fifo.
+ * Put a vlc_frame_t in the decoder's fifo.
  * Thread-safe w.r.t. the decoder. May be a cancellation point.
  *
  * \param p_dec the decoder object
- * \param p_block the data block
+ * \param p_frame the data frame
  */
-void input_DecoderDecode( decoder_t *p_dec, block_t *p_block, bool b_do_pace )
+void input_DecoderDecode( decoder_t *p_dec, vlc_frame_t *p_frame, bool b_do_pace )
 {
     struct decoder_owner *p_owner = dec_get_owner( p_dec );
 
@@ -2169,8 +2169,8 @@ void input_DecoderDecode( decoder_t *p_dec, block_t *p_block, bool b_do_pace )
         {
             msg_Warn( p_dec, "decoder/packetizer fifo full (data not "
                       "consumed quickly enough), resetting fifo!" );
-            block_ChainRelease( vlc_fifo_DequeueAllUnlocked( p_owner->p_fifo ) );
-            p_block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
+            vlc_frame_ChainRelease( vlc_frame_FifoDequeueAllUnlocked( p_owner->p_fifo ) );
+            p_frame->i_flags |= FRAME_FLAG_DISCONTINUITY;
         }
     }
     else
@@ -2182,7 +2182,7 @@ void input_DecoderDecode( decoder_t *p_dec, block_t *p_block, bool b_do_pace )
             vlc_fifo_WaitCond( p_owner->p_fifo, &p_owner->wait_fifo );
     }
 
-    vlc_fifo_QueueUnlocked( p_owner->p_fifo, p_block );
+    vlc_frame_FifoQueueUnlocked( p_owner->p_fifo, p_frame );
     vlc_fifo_Unlock( p_owner->p_fifo );
 }
 
@@ -2220,7 +2220,7 @@ bool input_DecoderIsEmpty( decoder_t * p_dec )
 }
 
 /**
- * Signals that there are no further blocks to decode, and requests that the
+ * Signals that there are no further frames to decode, and requests that the
  * decoder drain all pending buffers. This is used to ensure that all
  * intermediate buffers empty and no samples get lost at the end of the stream.
  *
@@ -2248,7 +2248,7 @@ void input_DecoderFlush( decoder_t *p_dec )
     vlc_fifo_Lock( p_owner->p_fifo );
 
     /* Empty the fifo */
-    block_ChainRelease( vlc_fifo_DequeueAllUnlocked( p_owner->p_fifo ) );
+    vlc_frame_ChainRelease( vlc_frame_FifoDequeueAllUnlocked( p_owner->p_fifo ) );
 
     /* Don't need to wait for the DecoderThread to flush. Indeed, if called a
      * second time, this function will clear the FIFO again before anything was
@@ -2506,7 +2506,7 @@ size_t input_DecoderGetFifoSize( decoder_t *p_dec )
 {
     struct decoder_owner *p_owner = dec_get_owner( p_dec );
 
-    return block_FifoSize( p_owner->p_fifo );
+    return vlc_frame_FifoSize( p_owner->p_fifo );
 }
 
 void input_DecoderSetVoutMouseEvent( decoder_t *dec, vlc_mouse_event mouse_event,
diff --git a/src/input/demux_chained.c b/src/input/demux_chained.c
index f2123fd0f7..b151ee875b 100644
--- a/src/input/demux_chained.c
+++ b/src/input/demux_chained.c
@@ -131,11 +131,12 @@ vlc_demux_chained_t *vlc_demux_chained_New(vlc_object_t *parent,
     return dc;
 }
 
-void vlc_demux_chained_Send(vlc_demux_chained_t *dc, block_t *block)
+void vlc_demux_chained_Send(vlc_demux_chained_t *dc, vlc_data_t * data)
 {
-    vlc_stream_fifo_Queue(dc->writer, block);
+    vlc_stream_fifo_Queue(dc->writer, data);
 }
 
+
 int vlc_demux_chained_ControlVa(vlc_demux_chained_t *dc, int query, va_list ap)
 {
     switch (query)
diff --git a/src/input/es_out.c b/src/input/es_out.c
index 3352602849..fd66249a01 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -34,7 +34,7 @@
 
 #include <vlc_input.h>
 #include <vlc_es_out.h>
-#include <vlc_block.h>
+#include <vlc_frame.h>
 #include <vlc_aout.h>
 #include <vlc_fourcc.h>
 #include <vlc_meta.h>
@@ -2216,51 +2216,51 @@ static void EsOutCreateCCChannels( es_out_t *out, vlc_fourcc_t codec, uint64_t i
 }
 
 /**
- * Send a block for the given es_out
+ * Send a frame for the given es_out
  *
  * \param out the es_out to send from
  * \param es the es_out_id
- * \param p_block the data block to send
+ * \param p_frame the data frame to send
  */
-static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
+static int EsOutSend( es_out_t *out, es_out_id_t *es, vlc_frame_t *p_frame )
 {
     es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
     input_thread_t *p_input = p_sys->p_input;
 
-    assert( p_block->p_next == NULL );
+    assert( p_frame->p_next == NULL );
 
     struct input_stats *stats = input_priv(p_input)->stats;
     if( stats != NULL )
     {
-        input_rate_Add( &stats->demux_bitrate, p_block->i_buffer );
+        input_rate_Add( &stats->demux_bitrate, p_frame->i_buffer );
 
         /* Update number of corrupted data packats */
-        if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
+        if( p_frame->i_flags & FRAME_FLAG_CORRUPTED )
             atomic_fetch_add_explicit(&stats->demux_corrupted, 1,
                                       memory_order_relaxed);
 
         /* Update number of discontinuities */
-        if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
+        if( p_frame->i_flags & FRAME_FLAG_DISCONTINUITY )
             atomic_fetch_add_explicit(&stats->demux_discontinuity, 1,
                                       memory_order_relaxed);
     }
 
     vlc_mutex_lock( &p_sys->lock );
 
-    /* Mark preroll blocks */
+    /* Mark preroll frames */
     if( p_sys->i_preroll_end >= 0 )
     {
-        vlc_tick_t i_date = p_block->i_pts;
-        if( p_block->i_pts == VLC_TICK_INVALID )
-            i_date = p_block->i_dts;
+        vlc_tick_t i_date = p_frame->i_pts;
+        if( p_frame->i_pts == VLC_TICK_INVALID )
+            i_date = p_frame->i_dts;
 
-        if( i_date + p_block->i_length < p_sys->i_preroll_end )
-            p_block->i_flags |= BLOCK_FLAG_PREROLL;
+        if( i_date + p_frame->i_length < p_sys->i_preroll_end )
+            p_frame->i_flags |= FRAME_FLAG_PREROLL;
     }
 
     if( !es->p_dec )
     {
-        block_Release( p_block );
+        vlc_frame_Release( p_frame );
         vlc_mutex_unlock( &p_sys->lock );
         return VLC_SUCCESS;
     }
@@ -2286,12 +2286,12 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
     /* Decode */
     if( es->p_dec_record )
     {
-        block_t *p_dup = block_Duplicate( p_block );
+        vlc_frame_t *p_dup = vlc_frame_Duplicate( p_frame );
         if( p_dup )
             input_DecoderDecode( es->p_dec_record, p_dup,
                                  input_priv(p_input)->b_out_pace_control );
     }
-    input_DecoderDecode( es->p_dec, p_block,
+    input_DecoderDecode( es->p_dec, p_frame,
                          input_priv(p_input)->b_out_pace_control );
 
     es_format_t fmt_dsc;
diff --git a/src/input/es_out_timeshift.c b/src/input/es_out_timeshift.c
index 406c6f2237..1b8295a215 100644
--- a/src/input/es_out_timeshift.c
+++ b/src/input/es_out_timeshift.c
@@ -45,7 +45,7 @@
 #endif
 #include <vlc_input.h>
 #include <vlc_es_out.h>
-#include <vlc_block.h>
+#include <vlc_frame.h>
 #include "input_internal.h"
 #include "es_out.h"
 
@@ -82,7 +82,7 @@ typedef struct attribute_packed
 typedef struct attribute_packed
 {
     es_out_id_t *p_es;
-    block_t *p_block;
+    vlc_frame_t *p_frame;
     int     i_offset;  /* We do not use file > INT_MAX */
 } ts_cmd_send_t;
 
@@ -275,7 +275,7 @@ static void CmdClean( ts_cmd_t * );
 static void cmd_cleanup_routine( void *p ) { CmdClean( p ); }
 
 static int  CmdInitAdd    ( ts_cmd_t *, es_out_id_t *, const es_format_t *, bool b_copy );
-static void CmdInitSend   ( ts_cmd_t *, es_out_id_t *, block_t * );
+static void CmdInitSend   ( ts_cmd_t *, es_out_id_t *, vlc_frame_t * );
 static int  CmdInitDel    ( ts_cmd_t *, es_out_id_t * );
 static int  CmdInitControl( ts_cmd_t *, int i_query, va_list, bool b_copy );
 
@@ -440,7 +440,7 @@ static es_out_id_t *Add( es_out_t *p_out, const es_format_t *p_fmt )
 
     return p_es;
 }
-static int Send( es_out_t *p_out, es_out_id_t *p_es, block_t *p_block )
+static int Send( es_out_t *p_out, es_out_id_t *p_es, vlc_frame_t *p_frame )
 {
     es_out_sys_t *p_sys = container_of(p_out, es_out_sys_t, out);
     ts_cmd_t cmd;
@@ -450,7 +450,7 @@ static int Send( es_out_t *p_out, es_out_id_t *p_es, block_t *p_block )
 
     TsAutoStop( p_out );
 
-    CmdInitSend( &cmd, p_es, p_block );
+    CmdInitSend( &cmd, p_es, p_frame );
     if( p_sys->b_delayed )
         TsPushCmd( p_sys->p_ts, &cmd );
     else
@@ -1209,7 +1209,7 @@ static bool TsStorageIsFull( ts_storage_t *p_storage, const ts_cmd_t *p_cmd )
 {
     if( p_cmd && p_cmd->i_type == C_SEND && p_storage->i_cmd_w > 0 )
     {
-        size_t i_size = sizeof(*p_cmd->u.send.p_block) + p_cmd->u.send.p_block->i_buffer;
+        size_t i_size = sizeof(*p_cmd->u.send.p_frame) + p_cmd->u.send.p_frame->i_buffer;
 
         if( p_storage->i_file_size + i_size >= p_storage->i_file_max )
             return true;
@@ -1228,27 +1228,27 @@ static void TsStoragePushCmd( ts_storage_t *p_storage, const ts_cmd_t *p_cmd, bo
 
     if( cmd.i_type == C_SEND )
     {
-        block_t *p_block = cmd.u.send.p_block;
+        vlc_frame_t *p_frame = cmd.u.send.p_frame;
 
-        cmd.u.send.p_block = NULL;
+        cmd.u.send.p_frame = NULL;
         cmd.u.send.i_offset = ftell( p_storage->p_filew );
 
-        if( fwrite( p_block, sizeof(*p_block), 1, p_storage->p_filew ) != 1 )
+        if( fwrite( p_frame, sizeof(*p_frame), 1, p_storage->p_filew ) != 1 )
         {
-            block_Release( p_block );
+            vlc_frame_Release( p_frame );
             return;
         }
-        p_storage->i_file_size += sizeof(*p_block);
-        if( p_block->i_buffer > 0 )
+        p_storage->i_file_size += sizeof(*p_frame);
+        if( p_frame->i_buffer > 0 )
         {
-            if( fwrite( p_block->p_buffer, p_block->i_buffer, 1, p_storage->p_filew ) != 1 )
+            if( fwrite( p_frame->p_buffer, p_frame->i_buffer, 1, p_storage->p_filew ) != 1 )
             {
-                block_Release( p_block );
+                vlc_frame_Release( p_frame );
                 return;
             }
         }
-        p_storage->i_file_size += p_block->i_buffer;
-        block_Release( p_block );
+        p_storage->i_file_size += p_frame->i_buffer;
+        vlc_frame_Release( p_frame );
 
         if( b_flush )
             fflush( p_storage->p_filew );
@@ -1262,28 +1262,28 @@ static void TsStoragePopCmd( ts_storage_t *p_storage, ts_cmd_t *p_cmd, bool b_fl
     *p_cmd = p_storage->p_cmd[p_storage->i_cmd_r++];
     if( p_cmd->i_type == C_SEND )
     {
-        block_t block;
+        vlc_frame_t frame;
 
         if( !b_flush &&
             !fseek( p_storage->p_filer, p_cmd->u.send.i_offset, SEEK_SET ) &&
-            fread( &block, sizeof(block), 1, p_storage->p_filer ) == 1 )
+            fread( &frame, sizeof(frame), 1, p_storage->p_filer ) == 1 )
         {
-            block_t *p_block = block_Alloc( block.i_buffer );
-            if( p_block )
+            vlc_frame_t *p_frame = vlc_frame_Alloc( frame.i_buffer );
+            if( p_frame )
             {
-                p_block->i_dts      = block.i_dts;
-                p_block->i_pts      = block.i_pts;
-                p_block->i_flags    = block.i_flags;
-                p_block->i_length   = block.i_length;
-                p_block->i_nb_samples = block.i_nb_samples;
-                p_block->i_buffer = fread( p_block->p_buffer, 1, block.i_buffer, p_storage->p_filer );
+                p_frame->i_dts      = frame.i_dts;
+                p_frame->i_pts      = frame.i_pts;
+                p_frame->i_flags    = frame.i_flags;
+                p_frame->i_length   = frame.i_length;
+                p_frame->i_nb_samples = frame.i_nb_samples;
+                p_frame->i_buffer = fread( p_frame->p_buffer, 1, frame.i_buffer, p_storage->p_filer );
             }
-            p_cmd->u.send.p_block = p_block;
+            p_cmd->u.send.p_frame = p_frame;
         }
         else
         {
             //perror( "TsStoragePopCmd" );
-            p_cmd->u.send.p_block = block_Alloc( 1 );
+            p_cmd->u.send.p_frame = vlc_frame_Alloc( 1 );
         }
     }
 }
@@ -1340,31 +1340,31 @@ static void CmdCleanAdd( ts_cmd_t *p_cmd )
     free( p_cmd->u.add.p_fmt );
 }
 
-static void CmdInitSend( ts_cmd_t *p_cmd, es_out_id_t *p_es, block_t *p_block )
+static void CmdInitSend( ts_cmd_t *p_cmd, es_out_id_t *p_es, vlc_frame_t *p_frame )
 {
     p_cmd->i_type = C_SEND;
     p_cmd->i_date = vlc_tick_now();
     p_cmd->u.send.p_es = p_es;
-    p_cmd->u.send.p_block = p_block;
+    p_cmd->u.send.p_frame = p_frame;
 }
 static int CmdExecuteSend( es_out_t *p_out, ts_cmd_t *p_cmd )
 {
-    block_t *p_block = p_cmd->u.send.p_block;
+    vlc_frame_t *p_frame = p_cmd->u.send.p_frame;
 
-    p_cmd->u.send.p_block = NULL;
+    p_cmd->u.send.p_frame = NULL;
 
-    if( p_block )
+    if( p_frame )
     {
         if( p_cmd->u.send.p_es->p_es )
-            return es_out_Send( p_out, p_cmd->u.send.p_es->p_es, p_block );
-        block_Release( p_block );
+            return es_out_Send( p_out, p_cmd->u.send.p_es->p_es, p_frame );
+        vlc_frame_Release( p_frame );
     }
     return VLC_EGENERIC;
 }
 static void CmdCleanSend( ts_cmd_t *p_cmd )
 {
-    if( p_cmd->u.send.p_block )
-        block_Release( p_cmd->u.send.p_block );
+    if( p_cmd->u.send.p_frame )
+        vlc_frame_Release( p_cmd->u.send.p_frame );
 }
 
 static int CmdInitDel( ts_cmd_t *p_cmd, es_out_id_t *p_es )
diff --git a/src/input/stream.c b/src/input/stream.c
index 35c5a04870..13135bb8eb 100644
--- a/src/input/stream.c
+++ b/src/input/stream.c
@@ -33,7 +33,7 @@
 #include <errno.h>
 
 #include <vlc_common.h>
-#include <vlc_block.h>
+#include <vlc_data.h>
 #include <vlc_access.h>
 #include <vlc_charset.h>
 #include <vlc_interrupt.h>
@@ -47,8 +47,8 @@ typedef struct stream_priv_t
 {
     stream_t stream;
     void (*destroy)(stream_t *);
-    block_t *block;
-    block_t *peek;
+    vlc_data_t *data;
+    vlc_data_t *peek;
     uint64_t offset;
     bool eof;
 
@@ -87,7 +87,7 @@ stream_t *vlc_stream_CustomNew(vlc_object_t *parent,
     s->p_input_item = NULL;
     assert(destroy != NULL);
     priv->destroy = destroy;
-    priv->block = NULL;
+    priv->data = NULL;
     priv->peek = NULL;
     priv->offset = 0;
     priv->eof = false;
@@ -119,9 +119,9 @@ void stream_CommonDelete(stream_t *s)
         vlc_iconv_close(priv->text.conv);
 
     if (priv->peek != NULL)
-        block_Release(priv->peek);
-    if (priv->block != NULL)
-        block_Release(priv->block);
+        vlc_data_Release(priv->peek);
+    if (priv->data != NULL)
+        vlc_data_Release(priv->data);
 
     free(s->psz_url);
     vlc_object_delete(s);
@@ -376,26 +376,26 @@ error:
     return NULL;
 }
 
-static ssize_t vlc_stream_CopyBlock(block_t **restrict pp,
+static ssize_t vlc_stream_CopyBlock(vlc_data_t **restrict pp,
                                     void *buf, size_t len)
 {
-    block_t *block = *pp;
+    vlc_data_t *data = *pp;
 
-    if (block == NULL)
+    if (data == NULL)
         return -1;
 
-    if (len > block->i_buffer)
-        len = block->i_buffer;
+    if (len > data->i_buffer)
+        len = data->i_buffer;
 
     if (buf != NULL)
-        memcpy(buf, block->p_buffer, len);
+        memcpy(buf, data->p_buffer, len);
 
-    block->p_buffer += len;
-    block->i_buffer -= len;
+    data->p_buffer += len;
+    data->i_buffer -= len;
 
-    if (block->i_buffer == 0)
+    if (data->i_buffer == 0)
     {
-        block_Release(block);
+        vlc_data_Release(data);
         *pp = NULL;
     }
 
@@ -414,7 +414,7 @@ static ssize_t vlc_stream_ReadRaw(stream_t *s, void *buf, size_t len)
 
     if (s->pf_read != NULL)
     {
-        assert(priv->block == NULL);
+        assert(priv->data == NULL);
         if (buf == NULL)
         {
             if (unlikely(len == 0))
@@ -428,7 +428,7 @@ static ssize_t vlc_stream_ReadRaw(stream_t *s, void *buf, size_t len)
         return ret;
     }
 
-    ret = vlc_stream_CopyBlock(&priv->block, buf, len);
+    ret = vlc_stream_CopyBlock(&priv->data, buf, len);
     if (ret >= 0)
         return ret;
 
@@ -436,8 +436,8 @@ static ssize_t vlc_stream_ReadRaw(stream_t *s, void *buf, size_t len)
     {
         bool eof = false;
 
-        priv->block = s->pf_block(s, &eof);
-        ret = vlc_stream_CopyBlock(&priv->block, buf, len);
+        priv->data = s->pf_block(s, &eof);
+        ret = vlc_stream_CopyBlock(&priv->data, buf, len);
         if (ret >= 0)
             return ret;
         return eof ? 0 : -1;
@@ -493,19 +493,19 @@ ssize_t vlc_stream_Read(stream_t *s, void *buf, size_t len)
 ssize_t vlc_stream_Peek(stream_t *s, const uint8_t **restrict bufp, size_t len)
 {
     stream_priv_t *priv = (stream_priv_t *)s;
-    block_t *peek;
+    vlc_data_t *peek;
 
     peek = priv->peek;
     if (peek == NULL)
     {
-        peek = priv->block;
+        peek = priv->data;
         priv->peek = peek;
-        priv->block = NULL;
+        priv->data = NULL;
     }
 
     if (peek == NULL)
     {
-        peek = block_Alloc(len);
+        peek = vlc_data_Alloc(len);
         if (unlikely(peek == NULL))
             return VLC_ENOMEM;
 
@@ -516,7 +516,7 @@ ssize_t vlc_stream_Peek(stream_t *s, const uint8_t **restrict bufp, size_t len)
     {
         size_t avail = peek->i_buffer;
 
-        peek = block_TryRealloc(peek, 0, len);
+        peek = vlc_data_TryRealloc(peek, 0, len);
         if (unlikely(peek == NULL))
             return VLC_ENOMEM;
 
@@ -544,10 +544,10 @@ ssize_t vlc_stream_Peek(stream_t *s, const uint8_t **restrict bufp, size_t len)
     return len;
 }
 
-block_t *vlc_stream_ReadBlock(stream_t *s)
+vlc_data_t *vlc_stream_ReadBlock(stream_t *s)
 {
     stream_priv_t *priv = (stream_priv_t *)s;
-    block_t *block;
+    vlc_data_t *data;
 
     if (vlc_killed())
     {
@@ -557,41 +557,41 @@ block_t *vlc_stream_ReadBlock(stream_t *s)
 
     if (priv->peek != NULL)
     {
-        block = priv->peek;
+        data = priv->peek;
         priv->peek = NULL;
     }
-    else if (priv->block != NULL)
+    else if (priv->data != NULL)
     {
-        block = priv->block;
-        priv->block = NULL;
+        data = priv->data;
+        priv->data = NULL;
     }
     else if (s->pf_block != NULL)
     {
         priv->eof = false;
-        block = s->pf_block(s, &priv->eof);
+        data = s->pf_block(s, &priv->eof);
     }
     else
     {
-        block = block_Alloc(4096);
-        if (unlikely(block == NULL))
+        data = vlc_data_Alloc(4096);
+        if (unlikely(data == NULL))
             return NULL;
 
-        ssize_t ret = s->pf_read(s, block->p_buffer, block->i_buffer);
+        ssize_t ret = s->pf_read(s, data->p_buffer, data->i_buffer);
         if (ret > 0)
-            block->i_buffer = ret;
+            data->i_buffer = ret;
         else
         {
-            block_Release(block);
-            block = NULL;
+            vlc_data_Release(data);
+            data = NULL;
         }
 
         priv->eof = !ret;
     }
 
-    if (block != NULL)
-        priv->offset += block->i_buffer;
+    if (data != NULL)
+        priv->offset += data->i_buffer;
 
-    return block;
+    return data;
 }
 
 uint64_t vlc_stream_Tell(const stream_t *s)
@@ -614,7 +614,7 @@ int vlc_stream_Seek(stream_t *s, uint64_t offset)
 
     priv->eof = false;
 
-    block_t *peek = priv->peek;
+    vlc_data_t *peek = priv->peek;
     if (peek != NULL)
     {
         if (offset >= priv->offset
@@ -629,7 +629,7 @@ int vlc_stream_Seek(stream_t *s, uint64_t offset)
             if (peek->i_buffer == 0)
             {
                 priv->peek = NULL;
-                block_Release(peek);
+                vlc_data_Release(peek);
             }
 
             return VLC_SUCCESS;
@@ -653,13 +653,13 @@ int vlc_stream_Seek(stream_t *s, uint64_t offset)
     if (peek != NULL)
     {
         priv->peek = NULL;
-        block_Release(peek);
+        vlc_data_Release(peek);
     }
 
-    if (priv->block != NULL)
+    if (priv->data != NULL)
     {
-        block_Release(priv->block);
-        priv->block = NULL;
+        vlc_data_Release(priv->data);
+        priv->data = NULL;
     }
 
     return VLC_SUCCESS;
@@ -687,14 +687,14 @@ int vlc_stream_vaControl(stream_t *s, int cmd, va_list args)
 
             if (priv->peek != NULL)
             {
-                block_Release(priv->peek);
+                vlc_data_Release(priv->peek);
                 priv->peek = NULL;
             }
 
-            if (priv->block != NULL)
+            if (priv->data != NULL)
             {
-                block_Release(priv->block);
-                priv->block = NULL;
+                vlc_data_Release(priv->data);
+                priv->data = NULL;
             }
 
             return VLC_SUCCESS;
@@ -712,24 +712,24 @@ int vlc_stream_vaControl(stream_t *s, int cmd, va_list args)
  @ note The block size may be shorter than requested if the end-of-stream was
  * reached.
  */
-block_t *vlc_stream_Block( stream_t *s, size_t size )
+vlc_frame_t *vlc_stream_Frame( stream_t *s, size_t size )
 {
     if( unlikely(size > SSIZE_MAX) )
         return NULL;
 
-    block_t *block = block_Alloc( size );
-    if( unlikely(block == NULL) )
+    vlc_frame_t *frame = vlc_frame_Alloc( size );
+    if( unlikely(frame == NULL) )
         return NULL;
 
-    ssize_t val = vlc_stream_Read( s, block->p_buffer, size );
+    ssize_t val = vlc_stream_Read( s, frame->p_buffer, size );
     if( val <= 0 )
     {
-        block_Release( block );
+        vlc_frame_Release( frame );
         return NULL;
     }
 
-    block->i_buffer = val;
-    return block;
+    frame->i_buffer = val;
+    return frame;
 }
 
 int vlc_stream_ReadDir( stream_t *s, input_item_node_t *p_node )
diff --git a/src/input/stream_extractor.c b/src/input/stream_extractor.c
index f340646768..6420aff0ad 100644
--- a/src/input/stream_extractor.c
+++ b/src/input/stream_extractor.c
@@ -150,7 +150,7 @@ se_StreamRead( stream_t* stream, void* buf, size_t len )
     return priv->extractor.pf_read( &priv->extractor, buf, len );
 }
 
-static block_t*
+static vlc_data_t*
 se_StreamBlock( stream_t* stream, bool* eof )
 {
     struct stream_extractor_private* priv = stream->p_sys;
diff --git a/src/input/stream_fifo.c b/src/input/stream_fifo.c
index 4cdd548016..8042a030f4 100644
--- a/src/input/stream_fifo.c
+++ b/src/input/stream_fifo.c
@@ -28,13 +28,17 @@
 #include <stdlib.h>
 
 #include <vlc_common.h>
-#include <vlc_block.h>
+#include <vlc_data.h>
 #include <vlc_stream.h>
 
 #include "stream.h"
 
 struct vlc_stream_fifo {
-    vlc_fifo_t *fifo;
+    vlc_mutex_t lock; /* fifo data lock */
+    vlc_cond_t wait; /* Wait for data */
+
+    vlc_data_t *p_first;
+    vlc_data_t **pp_last;
     bool eof;
 };
 
@@ -45,60 +49,61 @@ struct vlc_stream_fifo_private {
 static vlc_stream_fifo_t *vlc_stream_fifo_Writer(stream_t *s)
 {
     struct vlc_stream_fifo_private *sys = vlc_stream_Private(s);
-
     return sys->writer;
 }
 
 static void vlc_stream_fifo_Destroy(stream_t *s)
 {
     struct vlc_stream_fifo *writer = vlc_stream_fifo_Writer(s);
-    vlc_fifo_t *fifo = writer->fifo;
-    block_t *block;
+    vlc_data_t * data;
     bool closed;
 
-    vlc_fifo_Lock(fifo);
-    block = vlc_fifo_DequeueAllUnlocked(fifo);
+    vlc_mutex_lock(&writer->lock);
+    data = writer->p_first;
+    writer->p_first = NULL;
+    writer->pp_last = NULL;
     closed = writer->eof;
     writer->eof = true;
-    vlc_fifo_Unlock(fifo);
+    vlc_mutex_unlock(&writer->lock);
 
-    block_ChainRelease(block);
+    vlc_data_ChainRelease(data);
 
     if (closed) {
         /* Destroy shared state if write end is already closed */
-        block_FifoRelease(fifo);
+        vlc_cond_destroy(&writer->wait);
+        vlc_mutex_destroy(&writer->lock);
         free(writer);
     }
 }
 
-static block_t *vlc_stream_fifo_Block(stream_t *s, bool *restrict eof)
+static vlc_data_t *vlc_stream_fifo_Block(stream_t *s, bool *restrict eof)
 {
     struct vlc_stream_fifo *sys = vlc_stream_fifo_Writer(s);
-    vlc_fifo_t *fifo = sys->fifo;
-    block_t *block;
-
-    vlc_fifo_Lock(fifo);
-    while (vlc_fifo_IsEmpty(fifo))
-    {
-        if (sys->eof)
-        {
+    vlc_data_t *data;
+
+    vlc_mutex_lock(&sys->lock);
+    while (sys->p_first == NULL) {
+        if (sys->eof) {
             *eof = true;
-            break;
+            vlc_mutex_unlock(&sys->lock);
+            return NULL;
         }
-        vlc_fifo_Wait(fifo);
+        vlc_cond_wait(&sys->wait, &sys->lock);
     }
+    data = sys->p_first;
+    sys->p_first = data->p_next;
+    if (sys->p_first == NULL)
+        sys->pp_last = &sys->p_first;
 
-    block = vlc_fifo_DequeueUnlocked(fifo);
-    vlc_fifo_Unlock(fifo);
-    return block;
+    vlc_mutex_unlock(&sys->lock);
+    return data;
 }
 
 static int vlc_stream_fifo_Control(stream_t *s, int query, va_list ap)
 {
     (void) s;
 
-    switch (query)
-    {
+    switch (query) {
         case STREAM_CAN_SEEK:
         case STREAM_CAN_FASTSEEK:
         case STREAM_CAN_PAUSE:
@@ -122,18 +127,18 @@ vlc_stream_fifo_t *vlc_stream_fifo_New(vlc_object_t *parent, stream_t **reader)
     if (unlikely(writer == NULL))
         return NULL;
 
-    writer->fifo = block_FifoNew();
-    if (unlikely(writer->fifo == NULL)) {
-        free(writer);
-        return NULL;
-    }
+    vlc_mutex_init(&writer->lock);
+    vlc_cond_init(&writer->wait);
+    writer->p_first = NULL;
+    writer->pp_last = &writer->p_first;
     writer->eof = false;
 
     struct vlc_stream_fifo_private *sys;
     stream_t *s = vlc_stream_CustomNew(parent, vlc_stream_fifo_Destroy,
                                        sizeof (*sys), "stream");
     if (unlikely(s == NULL)) {
-        block_FifoRelease(writer->fifo);
+        vlc_cond_destroy(&writer->wait);
+        vlc_mutex_destroy(&writer->lock);
         free(writer);
         return NULL;
     }
@@ -147,21 +152,23 @@ vlc_stream_fifo_t *vlc_stream_fifo_New(vlc_object_t *parent, stream_t **reader)
     return writer;
 }
 
-int vlc_stream_fifo_Queue(vlc_stream_fifo_t *writer, block_t *block)
+int vlc_stream_fifo_Queue(vlc_stream_fifo_t *writer, vlc_data_t *data)
 {
-    vlc_fifo_t *fifo = writer->fifo;
-
-    vlc_fifo_Lock(fifo);
-    if (likely(!writer->eof))
-    {
-        vlc_fifo_QueueUnlocked(fifo, block);
-        block = NULL;
+    vlc_mutex_lock(&writer->lock);
+    if (likely(!writer->eof)) {
+        for (*writer->pp_last = data; data != NULL; data = data->p_next)
+            writer->pp_last = &data->p_next;
+        vlc_cond_signal(&writer->wait);
     }
-    vlc_fifo_Unlock(fifo);
-
-    if (unlikely(block != NULL))
-    {
-        block_Release(block);
+    vlc_mutex_unlock(&writer->lock);
+
+    if (unlikely(data != NULL)) {
+        vlc_data_t * tmp;
+        while (data != NULL) {
+            tmp = data;
+            data = data->p_next;
+            vlc_data_Release(tmp);
+        }
         errno = EPIPE;
         return -1;
     }
@@ -171,28 +178,28 @@ int vlc_stream_fifo_Queue(vlc_stream_fifo_t *writer, block_t *block)
 ssize_t vlc_stream_fifo_Write(vlc_stream_fifo_t *writer,
                               const void *buf, size_t len)
 {
-    block_t *block = block_Alloc(len);
-    if (unlikely(block == NULL))
+    vlc_data_t *data = vlc_data_Alloc(len);
+    if (unlikely(data == NULL))
         return -1;
 
-    memcpy(block->p_buffer, buf, len);
-    return vlc_stream_fifo_Queue(writer, block) ? -1 : (ssize_t)len;
+    memcpy(data->p_buffer, buf, len);
+    return vlc_stream_fifo_Queue(writer, data) ? -1 : (ssize_t)len;
 }
 
 void vlc_stream_fifo_Close(vlc_stream_fifo_t *writer)
 {
-    vlc_fifo_t *fifo = writer->fifo;
     bool closed;
 
-    vlc_fifo_Lock(fifo);
+    vlc_mutex_lock(&writer->lock);
     closed = writer->eof;
     writer->eof = true;
-    vlc_fifo_Signal(fifo);
-    vlc_fifo_Unlock(fifo);
+    vlc_cond_signal(&writer->wait);
+    vlc_mutex_unlock(&writer->lock);
 
     if (closed) {
         /* Destroy shared state if read end is already closed */
-        block_FifoRelease(fifo);
+        vlc_cond_destroy(&writer->wait);
+        vlc_mutex_destroy(&writer->lock);
         free(writer);
     }
 }
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index ed5e1ee661..aae332ecb3 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -30,23 +30,40 @@ aout_FiltersPlay
 aout_FiltersAdjustResampling
 aout_Hold
 aout_Release
-block_Alloc
-block_FifoCount
-block_FifoEmpty
-block_FifoGet
-block_FifoNew
-block_FifoPut
-block_FifoRelease
-block_FifoShow
-block_File
-block_FilePath
-block_heap_Alloc
-block_Init
-block_mmap_Alloc
-block_shm_Alloc
-block_Realloc
-block_Release
-block_TryRealloc
+vlc_data_Alloc
+vlc_data_FifoCount
+vlc_data_FifoDequeueAllUnlocked
+vlc_data_FifoEmpty
+vlc_data_FifoGet
+vlc_data_FifoNew
+vlc_data_FifoPut
+vlc_data_FifoRelease
+vlc_data_File
+vlc_data_FilePath
+vlc_data_heap_Alloc
+vlc_data_Init
+vlc_data_mmap_Alloc
+vlc_data_shm_Alloc
+vlc_data_Realloc
+vlc_data_Release
+vlc_data_TryRealloc
+vlc_frame_Alloc
+vlc_frame_FifoCount
+vlc_frame_FifoEmpty
+vlc_frame_FifoGet
+vlc_frame_FifoNew
+vlc_frame_FifoPut
+vlc_frame_FifoRelease
+vlc_frame_FifoShow
+vlc_frame_File
+vlc_frame_FilePath
+vlc_frame_heap_Alloc
+vlc_frame_Init
+vlc_frame_mmap_Alloc
+vlc_frame_shm_Alloc
+vlc_frame_Realloc
+vlc_frame_Release
+vlc_frame_TryRealloc
 config_AddIntf
 config_ChainCreate
 config_ChainDestroy
@@ -408,7 +425,7 @@ spu_ClearChannel
 vlc_stream_directory_Attach
 vlc_stream_extractor_Attach
 vlc_stream_extractor_CreateMRL
-vlc_stream_Block
+vlc_stream_Frame
 vlc_stream_CommonNew
 vlc_stream_Delete
 vlc_stream_Eof
@@ -727,9 +744,9 @@ vlc_fifo_Unlock
 vlc_fifo_Signal
 vlc_fifo_Wait
 vlc_fifo_WaitCond
-vlc_fifo_QueueUnlocked
-vlc_fifo_DequeueUnlocked
-vlc_fifo_DequeueAllUnlocked
+vlc_frame_FifoQueueUnlocked
+vlc_frame_FifoDequeueUnlocked
+vlc_frame_FifoDequeueAllUnlocked
 vlc_fifo_GetCount
 vlc_fifo_GetBytes
 vlc_gl_Create
diff --git a/src/misc/data.c b/src/misc/data.c
new file mode 100644
index 0000000000..f3ad33802b
--- /dev/null
+++ b/src/misc/data.c
@@ -0,0 +1,426 @@
+/*****************************************************************************
+ * data.c: Data datas management functions
+ *****************************************************************************
+ * Copyright (C) 2003-2004 VLC authors and VideoLAN
+ * Copyright (C) 2007-2009 RĂ©mi Denis-Courmont
+ *
+ * Authors: Laurent Aimar <fenrir at videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <sys/stat.h>
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <vlc_common.h>
+#include <vlc_data.h>
+#include <vlc_fs.h>
+
+#ifndef NDEBUG
+static void vlc_data_Check(vlc_data_t * data)
+{
+    while (data != NULL)
+    {
+        unsigned char *start = data->p_start;
+        unsigned char *end = data->p_start + data->i_size;
+        unsigned char *bufstart = data->p_buffer;
+        unsigned char *bufend = data->p_buffer + data->i_buffer;
+        assert (start <= end);
+        assert (bufstart <= bufend);
+        assert (bufstart >= start);
+        assert (bufend <= end);
+        data = data->p_next;
+    }
+}
+#else
+# define vlc_data_Check(b) ((void)(b))
+#endif
+
+vlc_data_t *vlc_data_Init(vlc_data_t *restrict f,
+                            const struct vlc_data_callbacks *cbs,
+                            void *buf, size_t size)
+{
+    /* Fill all fields to their default */
+    f->p_next = NULL;
+    f->p_buffer = buf;
+    f->i_buffer = size;
+    f->p_start = buf;
+    f->i_size = size;
+    f->cbs = cbs;
+    return f;
+}
+
+static void vlc_data_generic_Release (vlc_data_t *data)
+{
+    /* That is always true for datas allocated with vlc_data_Alloc(). */
+    assert (data->p_start == (unsigned char *)(data + 1));
+    free (data);
+}
+
+static const struct vlc_data_callbacks vlc_data_generic_cbs =
+{
+    vlc_data_generic_Release,
+};
+
+/** Initial memory alignment of data data.
+ * @note This must be a multiple of sizeof(void*) and a power of two.
+ * libavcodec AVX optimizations require at least 32-bytes. */
+#define BLOCK_ALIGN        32
+
+/** Initial reserved header and footer size. */
+#define BLOCK_PADDING      32
+
+vlc_data_t *vlc_data_Alloc (size_t size)
+{
+    if (unlikely(size >> 27))
+    {
+        errno = ENOBUFS;
+        return NULL;
+    }
+
+    /* 2 * BLOCK_PADDING: pre + post padding */
+    const size_t alloc = sizeof (vlc_data_t) + BLOCK_ALIGN + (2 * BLOCK_PADDING)
+                       + size;
+    if (unlikely(alloc <= size))
+        return NULL;
+
+    vlc_data_t *b = malloc (alloc);
+    if (unlikely(b == NULL))
+        return NULL;
+
+    vlc_data_Init(b, &vlc_data_generic_cbs, b + 1, alloc - sizeof (*b));
+    static_assert ((BLOCK_PADDING % BLOCK_ALIGN) == 0,
+                   "BLOCK_PADDING must be a multiple of BLOCK_ALIGN");
+    b->p_buffer += BLOCK_PADDING + BLOCK_ALIGN - 1;
+    b->p_buffer = (void *)(((uintptr_t)b->p_buffer) & ~(BLOCK_ALIGN - 1));
+    b->i_buffer = size;
+    return b;
+}
+
+void vlc_data_Release(vlc_data_t *data)
+{
+#ifndef NDEBUG
+    data->p_next = NULL;
+    vlc_data_Check (data);
+#endif
+    data->cbs->free(data);
+}
+
+vlc_data_t *vlc_data_TryRealloc (vlc_data_t *p_data, ssize_t i_prebody, size_t i_body)
+{
+    vlc_data_Check( p_data );
+
+    /* Corner case: empty data requested */
+    if( i_prebody <= 0 && i_body <= (size_t)(-i_prebody) )
+        i_prebody = i_body = 0;
+
+    assert( p_data->p_start <= p_data->p_buffer );
+    assert( p_data->p_start + p_data->i_size
+                                    >= p_data->p_buffer + p_data->i_buffer );
+
+    /* First, shrink payload */
+
+    /* Pull payload start */
+    if( i_prebody < 0 )
+    {
+        if( p_data->i_buffer >= (size_t)-i_prebody )
+        {
+            p_data->p_buffer -= i_prebody;
+            p_data->i_buffer += i_prebody;
+        }
+        else /* Discard current payload entirely */
+            p_data->i_buffer = 0;
+        i_body += i_prebody;
+        i_prebody = 0;
+    }
+
+    /* Trim payload end */
+    if( p_data->i_buffer > i_body )
+        p_data->i_buffer = i_body;
+
+    size_t requested = i_prebody + i_body;
+
+    if( p_data->i_buffer == 0 )
+    {   /* Corner case: nothing to preserve */
+        if( requested <= p_data->i_size )
+        {   /* Enough room: recycle buffer */
+            size_t extra = p_data->i_size - requested;
+
+            p_data->p_buffer = p_data->p_start + (extra / 2);
+            p_data->i_buffer = requested;
+            return p_data;
+        }
+
+        /* Not enough room: allocate a new buffer */
+        vlc_data_t *p_rea = vlc_data_Alloc( requested );
+        if( p_rea == NULL )
+            return NULL;
+
+        p_rea->p_next = p_data->p_next;
+        vlc_data_Release( p_data );
+        return p_rea;
+    }
+
+    uint8_t *p_start = p_data->p_start;
+    uint8_t *p_end = p_start + p_data->i_size;
+
+    /* Second, reallocate the buffer if we lack space. */
+    assert( i_prebody >= 0 );
+    if( (size_t)(p_data->p_buffer - p_start) < (size_t)i_prebody
+     || (size_t)(p_end - p_data->p_buffer) < i_body )
+    {
+        vlc_data_t *p_rea = vlc_data_Alloc( requested );
+        if( p_rea == NULL )
+            return NULL;
+
+        memcpy( p_rea->p_buffer + i_prebody, p_data->p_buffer,
+                p_data->i_buffer );
+        p_rea->p_next = p_data->p_next;
+        vlc_data_Release( p_data );
+        return p_rea;
+    }
+
+    /* Third, expand payload */
+
+    /* Push payload start */
+    if( i_prebody > 0 )
+    {
+        p_data->p_buffer -= i_prebody;
+        p_data->i_buffer += i_prebody;
+        i_body += i_prebody;
+        i_prebody = 0;
+    }
+
+    /* Expand payload to requested size */
+    p_data->i_buffer = i_body;
+
+    return p_data;
+}
+
+vlc_data_t *vlc_data_Realloc (vlc_data_t *data, ssize_t prebody, size_t body)
+{
+    vlc_data_t *rea = vlc_data_TryRealloc (data, prebody, body);
+    if (rea == NULL)
+        vlc_data_Release(data);
+    return rea;
+}
+
+static void vlc_data_heap_Release (vlc_data_t *data)
+{
+    free (data->p_start);
+    free (data);
+}
+
+static const struct vlc_data_callbacks vlc_data_heap_cbs =
+{
+    vlc_data_heap_Release,
+};
+
+vlc_data_t *vlc_data_heap_Alloc (void *addr, size_t length)
+{
+    vlc_data_t *data = malloc (sizeof (*data));
+    if (data == NULL)
+    {
+        free (addr);
+        return NULL;
+    }
+
+    return vlc_data_Init(data, &vlc_data_heap_cbs, addr, length);
+}
+
+#ifdef HAVE_MMAP
+# include <sys/mman.h>
+
+static void vlc_data_mmap_Release (vlc_data_t *data)
+{
+    munmap (data->p_start, data->i_size);
+    free (data);
+}
+
+static const struct vlc_data_callbacks vlc_data_mmap_cbs =
+{
+    vlc_data_mmap_Release,
+};
+
+vlc_data_t *vlc_data_mmap_Alloc (void *addr, size_t length)
+{
+    if (addr == MAP_FAILED)
+        return NULL;
+
+    long page_mask = sysconf(_SC_PAGESIZE) - 1;
+    size_t left = ((uintptr_t)addr) & page_mask;
+    size_t right = (-length) & page_mask;
+
+    vlc_data_t *data = malloc (sizeof (*data));
+    if (data == NULL)
+    {
+        munmap (addr, length);
+        return NULL;
+    }
+
+    vlc_data_Init(data, &vlc_data_mmap_cbs,
+               ((char *)addr) - left, left + length + right);
+    data->p_buffer = addr;
+    data->i_buffer = length;
+    return data;
+}
+#else
+vlc_data_t *vlc_data_mmap_Alloc (void *addr, size_t length)
+{
+    (void)addr; (void)length; return NULL;
+}
+#endif
+
+#ifdef HAVE_SYS_SHM_H
+# include <sys/shm.h>
+
+static void vlc_data_shm_Release (vlc_data_t *data)
+{
+    shmdt(data->p_start);
+    free(data);
+}
+
+static const struct vlc_data_callbacks vlc_data_shm_cbs =
+{
+    vlc_data_shm_Release,
+};
+
+vlc_data_t *vlc_data_shm_Alloc (void *addr, size_t length)
+{
+    vlc_data_t *data = malloc (sizeof (*data));
+    if (unlikely(data == NULL))
+    {
+        shmdt (addr);
+        return NULL;
+    }
+
+    return vlc_data_Init(data, &vlc_data_shm_cbs, (uint8_t *)addr, length);
+}
+#else
+vlc_data_t *vlc_data_shm_Alloc (void *addr, size_t length)
+{
+    (void) addr; (void) length;
+    abort ();
+}
+#endif
+
+
+#ifdef _WIN32
+# include <io.h>
+
+static
+ssize_t pread (int fd, void *buf, size_t count, off_t offset)
+{
+    HANDLE handle = (HANDLE)(intptr_t)_get_osfhandle (fd);
+    if (handle == INVALID_HANDLE_VALUE)
+        return -1;
+
+    OVERLAPPED olap = {.Offset = offset, .OffsetHigh = (offset >> 32)};
+    DWORD written;
+    /* This braindead API will override the file pointer even if we specify
+     * an explicit read offset... So do not expect this to mix well with
+     * regular read() calls. */
+    if (ReadFile (handle, buf, count, &written, &olap))
+        return written;
+    return -1;
+}
+#endif
+
+vlc_data_t *vlc_data_File(int fd, bool write)
+{
+    size_t length;
+    struct stat st;
+
+    /* First, get the file size */
+    if (fstat (fd, &st))
+        return NULL;
+
+    /* st_size is meaningful for regular files, shared memory and typed memory.
+     * It's also meaning for symlinks, but that's not possible with fstat().
+     * In other cases, it's undefined, and we should really not go further. */
+#ifndef S_TYPEISSHM
+# define S_TYPEISSHM( buf ) (0)
+#endif
+    if (S_ISDIR (st.st_mode))
+    {
+        errno = EISDIR;
+        return NULL;
+    }
+    if (!S_ISREG (st.st_mode) && !S_TYPEISSHM (&st))
+    {
+        errno = ESPIPE;
+        return NULL;
+    }
+
+    /* Prevent an integer overflow in mmap() and malloc() */
+    if ((uintmax_t)st.st_size >= SIZE_MAX)
+    {
+        errno = ENOMEM;
+        return NULL;
+    }
+    length = (size_t)st.st_size;
+
+#ifdef HAVE_MMAP
+    if (length > 0)
+    {
+        int prot = PROT_READ | (write ? PROT_WRITE : 0);
+        int flags = write ? MAP_PRIVATE : MAP_SHARED;
+        void *addr = mmap(NULL, length, prot, flags, fd, 0);
+
+        if (addr != MAP_FAILED)
+            return vlc_data_mmap_Alloc (addr, length);
+    }
+#endif
+
+    /* If mmap() is not implemented by the OS _or_ the filesystem... */
+    vlc_data_t *data = vlc_data_Alloc (length);
+    if (data == NULL)
+        return NULL;
+    vlc_data_cleanup_push (data);
+
+    for (size_t i = 0; i < length;)
+    {
+        ssize_t len = pread (fd, data->p_buffer + i, length - i, i);
+        if (len == -1)
+        {
+            vlc_data_Release (data);
+            data = NULL;
+            break;
+        }
+        i += len;
+    }
+    vlc_cleanup_pop ();
+    return data;
+}
+
+vlc_data_t *vlc_data_FilePath(const char *path, bool write)
+{
+    /* NOTE: Writeable shared mappings are not supported here. So there are no
+     * needs to open the file for writing (even if the mapping is writable). */
+    int fd = vlc_open (path, O_RDONLY);
+    if (fd == -1)
+        return NULL;
+
+    vlc_data_t *data = vlc_data_File(fd, write);
+    vlc_close (fd);
+    return data;
+}
diff --git a/src/misc/fifo.c b/src/misc/fifo.c
index e11aebdb87..dfbd2699cc 100644
--- a/src/misc/fifo.c
+++ b/src/misc/fifo.c
@@ -29,21 +29,37 @@
 #include <stdlib.h>
 
 #include <vlc_common.h>
-#include <vlc_block.h>
+#include <vlc_data.h>
+#include <vlc_frame.h>
 #include "libvlc.h"
 
 /**
- * Internal state for block queues
+ * Internal state for frame queues
  */
-struct block_fifo_t
+typedef union
 {
-    vlc_mutex_t         lock;                         /* fifo data lock */
-    vlc_cond_t          wait;      /**< Wait for data */
+    vlc_frame_t * f;
+    vlc_data_t * d;
+} vlc_fifo_elem_t;
 
-    block_t             *p_first;
-    block_t             **pp_last;
-    size_t              i_depth;
-    size_t              i_size;
+typedef enum
+{
+    VLC_FRAME_FIFO,
+    VLC_DATA_FIFO
+} vlc_fifo_type_t;
+
+struct vlc_fifo_t
+{
+    vlc_mutex_t lock; /* fifo data lock */
+    vlc_cond_t wait; /**< Wait for data */
+
+    void * p_first;
+    void **pp_last;
+    size_t i_depth;
+    size_t i_size;
+#ifndef NDEBUG
+    vlc_fifo_type_t type;
+#endif
 };
 
 void vlc_fifo_Lock(vlc_fifo_t *fifo)
@@ -88,64 +104,67 @@ size_t vlc_fifo_GetBytes(const vlc_fifo_t *fifo)
     return fifo->i_size;
 }
 
-void vlc_fifo_QueueUnlocked(block_fifo_t *fifo, block_t *block)
+void vlc_frame_FifoQueueUnlocked(vlc_frame_fifo_t *fifo, vlc_frame_t *frame)
 {
+    assert(fifo->type == VLC_FRAME_FIFO);
     vlc_mutex_assert(&fifo->lock);
     assert(*(fifo->pp_last) == NULL);
 
-    *(fifo->pp_last) = block;
+    *(fifo->pp_last) = (void*) frame;
 
-    while (block != NULL)
+    while (frame != NULL)
     {
-        fifo->pp_last = &block->p_next;
+        fifo->pp_last = (void *) &frame->p_next;
         fifo->i_depth++;
-        fifo->i_size += block->i_buffer;
+        fifo->i_size += frame->i_buffer;
 
-        block = block->p_next;
+        frame = frame->p_next;
     }
 
     vlc_fifo_Signal(fifo);
 }
 
-block_t *vlc_fifo_DequeueUnlocked(block_fifo_t *fifo)
+vlc_frame_t *vlc_frame_FifoDequeueUnlocked(vlc_frame_fifo_t *fifo)
 {
+    assert(fifo->type == VLC_FRAME_FIFO);
     vlc_mutex_assert(&fifo->lock);
 
-    block_t *block = fifo->p_first;
+    vlc_frame_t *frame = (vlc_frame_t*) fifo->p_first;
 
-    if (block == NULL)
+    if (frame == NULL)
         return NULL; /* Nothing to do */
 
-    fifo->p_first = block->p_next;
-    if (block->p_next == NULL)
+    fifo->p_first = (void*) frame->p_next;
+    if (frame->p_next == NULL)
         fifo->pp_last = &fifo->p_first;
-    block->p_next = NULL;
+    frame->p_next = NULL;
 
     assert(fifo->i_depth > 0);
     fifo->i_depth--;
-    assert(fifo->i_size >= block->i_buffer);
-    fifo->i_size -= block->i_buffer;
+    assert(fifo->i_size >= frame->i_buffer);
+    fifo->i_size -= frame->i_buffer;
 
-    return block;
+    return frame;
 }
 
-block_t *vlc_fifo_DequeueAllUnlocked(block_fifo_t *fifo)
+vlc_frame_t *vlc_frame_FifoDequeueAllUnlocked(vlc_frame_fifo_t *fifo)
 {
+    assert(fifo->type == VLC_FRAME_FIFO);
     vlc_mutex_assert(&fifo->lock);
 
-    block_t *block = fifo->p_first;
+    vlc_frame_t *frame = (vlc_frame_t *) fifo->p_first;
 
     fifo->p_first = NULL;
     fifo->pp_last = &fifo->p_first;
     fifo->i_depth = 0;
     fifo->i_size = 0;
 
-    return block;
+    return frame;
 }
 
-block_fifo_t *block_FifoNew( void )
+vlc_frame_fifo_t *vlc_frame_FifoNew( void )
 {
-    block_fifo_t *p_fifo = malloc( sizeof( block_fifo_t ) );
+    vlc_frame_fifo_t *p_fifo = malloc( sizeof( vlc_frame_fifo_t ) );
     if( !p_fifo )
         return NULL;
 
@@ -155,37 +174,45 @@ block_fifo_t *block_FifoNew( void )
     p_fifo->pp_last = &p_fifo->p_first;
     p_fifo->i_depth = p_fifo->i_size = 0;
 
+#ifndef NDEBUG
+    p_fifo->type = VLC_FRAME_FIFO;
+#endif
+
     return p_fifo;
 }
 
-void block_FifoRelease( block_fifo_t *p_fifo )
+void vlc_frame_FifoRelease( vlc_frame_fifo_t *p_fifo )
 {
-    block_ChainRelease( p_fifo->p_first );
+    assert(p_fifo->type == VLC_FRAME_FIFO);
+    vlc_frame_ChainRelease((vlc_frame_t *) p_fifo->p_first );
     vlc_cond_destroy( &p_fifo->wait );
     vlc_mutex_destroy( &p_fifo->lock );
     free( p_fifo );
 }
 
-void block_FifoEmpty(block_fifo_t *fifo)
+void vlc_frame_FifoEmpty(vlc_frame_fifo_t *fifo)
 {
-    block_t *block;
+    assert(fifo->type == VLC_FRAME_FIFO);
+    vlc_frame_t *frame;
 
     vlc_fifo_Lock(fifo);
-    block = vlc_fifo_DequeueAllUnlocked(fifo);
+    frame = vlc_frame_FifoDequeueAllUnlocked(fifo);
     vlc_fifo_Unlock(fifo);
-    block_ChainRelease(block);
+    vlc_frame_ChainRelease(frame);
 }
 
-void block_FifoPut(block_fifo_t *fifo, block_t *block)
+void vlc_frame_FifoPut(vlc_frame_fifo_t *fifo, vlc_frame_t *frame)
 {
+    assert(fifo->type == VLC_FRAME_FIFO);
     vlc_fifo_Lock(fifo);
-    vlc_fifo_QueueUnlocked(fifo, block);
+    vlc_frame_FifoQueueUnlocked(fifo, frame);
     vlc_fifo_Unlock(fifo);
 }
 
-block_t *block_FifoGet(block_fifo_t *fifo)
+vlc_frame_t *vlc_frame_FifoGet(vlc_frame_fifo_t *fifo)
 {
-    block_t *block;
+    assert(fifo->type == VLC_FRAME_FIFO);
+    vlc_frame_t *frame;
 
     vlc_testcancel();
 
@@ -196,15 +223,16 @@ block_t *block_FifoGet(block_fifo_t *fifo)
         vlc_fifo_Wait(fifo);
         vlc_cleanup_pop();
     }
-    block = vlc_fifo_DequeueUnlocked(fifo);
+    frame = vlc_frame_FifoDequeueUnlocked(fifo);
     vlc_fifo_Unlock(fifo);
 
-    return block;
+    return frame;
 }
 
-block_t *block_FifoShow( block_fifo_t *p_fifo )
+vlc_frame_t *vlc_frame_FifoShow( vlc_frame_fifo_t *p_fifo )
 {
-    block_t *b;
+    assert(p_fifo->type == VLC_FRAME_FIFO);
+    vlc_frame_t *b;
 
     vlc_mutex_lock( &p_fifo->lock );
     assert(p_fifo->p_first != NULL);
@@ -215,8 +243,9 @@ block_t *block_FifoShow( block_fifo_t *p_fifo )
 }
 
 /* FIXME: not (really) thread-safe */
-size_t block_FifoSize (block_fifo_t *fifo)
+size_t vlc_frame_FifoSize (vlc_frame_fifo_t *fifo)
 {
+    assert(fifo->type == VLC_FRAME_FIFO);
     size_t size;
 
     vlc_mutex_lock (&fifo->lock);
@@ -226,8 +255,147 @@ size_t block_FifoSize (block_fifo_t *fifo)
 }
 
 /* FIXME: not (really) thread-safe */
-size_t block_FifoCount (block_fifo_t *fifo)
+size_t vlc_frame_FifoCount (vlc_frame_fifo_t *fifo)
+{
+    assert(fifo->type == VLC_FRAME_FIFO);
+    size_t depth;
+
+    vlc_mutex_lock (&fifo->lock);
+    depth = fifo->i_depth;
+    vlc_mutex_unlock (&fifo->lock);
+    return depth;
+}
+
+
+static void vlc_data_FifoQueueUnlocked(vlc_data_fifo_t *fifo, vlc_data_t *data)
+{
+    assert(fifo->type == VLC_DATA_FIFO);
+    vlc_mutex_assert(&fifo->lock);
+    assert(*(fifo->pp_last) == NULL);
+
+    *(fifo->pp_last) = (void*) data;
+
+    while (data != NULL)
+    {
+        fifo->pp_last = (void *) &data->p_next;
+        fifo->i_depth++;
+        fifo->i_size += data->i_buffer;
+
+        data = data->p_next;
+    }
+
+    vlc_fifo_Signal(fifo);
+}
+
+static vlc_data_t *vlc_data_FifoDequeueUnlocked(vlc_data_fifo_t *fifo)
+{
+    assert(fifo->type == VLC_DATA_FIFO);
+    vlc_mutex_assert(&fifo->lock);
+
+    vlc_data_t *data = (vlc_data_t*) fifo->p_first;
+
+    if (data == NULL)
+        return NULL; /* Nothing to do */
+
+    fifo->p_first = (void*) data->p_next;
+    if (data->p_next == NULL)
+        fifo->pp_last = &fifo->p_first;
+    data->p_next = NULL;
+
+    assert(fifo->i_depth > 0);
+    fifo->i_depth--;
+    assert(fifo->i_size >= data->i_buffer);
+    fifo->i_size -= data->i_buffer;
+
+    return data;
+}
+
+vlc_data_t *vlc_data_FifoDequeueAllUnlocked(vlc_data_fifo_t *fifo)
+{
+    assert(fifo->type == VLC_DATA_FIFO);
+    vlc_mutex_assert(&fifo->lock);
+
+    vlc_data_t *data = (vlc_data_t *) fifo->p_first;
+
+    fifo->p_first = NULL;
+    fifo->pp_last = &fifo->p_first;
+    fifo->i_depth = 0;
+    fifo->i_size = 0;
+
+    return data;
+}
+
+
+vlc_data_fifo_t *vlc_data_FifoNew( void )
+{
+    vlc_data_fifo_t *p_fifo = malloc( sizeof( vlc_data_fifo_t ) );
+    if( !p_fifo )
+        return NULL;
+
+    vlc_mutex_init( &p_fifo->lock );
+    vlc_cond_init( &p_fifo->wait );
+    p_fifo->p_first = NULL;
+    p_fifo->pp_last = &p_fifo->p_first;
+    p_fifo->i_depth = p_fifo->i_size = 0;
+
+#ifndef NDEBUG
+    p_fifo->type == VLC_DATA_FIFO;
+#endif
+
+    return p_fifo;
+}
+
+void vlc_data_FifoRelease( vlc_data_fifo_t *p_fifo )
+{
+    assert(p_fifo->type == VLC_DATA_FIFO);
+    vlc_data_ChainRelease( (vlc_data_t *)p_fifo->p_first );
+    vlc_cond_destroy( &p_fifo->wait );
+    vlc_mutex_destroy( &p_fifo->lock );
+    free( p_fifo );
+}
+
+void vlc_data_FifoEmpty(vlc_data_fifo_t *fifo)
+{
+    assert(fifo->type == VLC_DATA_FIFO);
+    vlc_data_t *data;
+
+    vlc_fifo_Lock(fifo);
+    data = vlc_data_FifoDequeueAllUnlocked(fifo);
+    vlc_fifo_Unlock(fifo);
+    vlc_data_ChainRelease(data);
+}
+
+void vlc_data_FifoPut(vlc_data_fifo_t *fifo, vlc_data_t *data)
+{
+    assert(fifo->type == VLC_DATA_FIFO);
+    vlc_fifo_Lock(fifo);
+    vlc_data_FifoQueueUnlocked(fifo, data);
+    vlc_fifo_Unlock(fifo);
+}
+
+vlc_data_t *vlc_data_FifoGet(vlc_data_fifo_t *fifo)
+{
+    assert(fifo->type == VLC_DATA_FIFO);
+    vlc_data_t *data;
+
+    vlc_testcancel();
+
+    vlc_fifo_Lock(fifo);
+    while (vlc_fifo_IsEmpty(fifo))
+    {
+        vlc_fifo_CleanupPush(fifo);
+        vlc_fifo_Wait(fifo);
+        vlc_cleanup_pop();
+    }
+    data = vlc_data_FifoDequeueUnlocked(fifo);
+    vlc_fifo_Unlock(fifo);
+
+    return data;
+}
+
+size_t vlc_data_FifoCount (vlc_data_fifo_t *fifo)
 {
+    assert(fifo->type == VLC_DATA_FIFO);
     size_t depth;
 
     vlc_mutex_lock (&fifo->lock);
diff --git a/src/misc/block.c b/src/misc/frame.c
similarity index 55%
rename from src/misc/block.c
rename to src/misc/frame.c
index 74da567145..2f96e76325 100644
--- a/src/misc/block.c
+++ b/src/misc/frame.c
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * block.c: Data blocks management functions
+ * frame.c: Data frames management functions
  *****************************************************************************
  * Copyright (C) 2003-2004 VLC authors and VideoLAN
  * Copyright (C) 2007-2009 RĂ©mi Denis-Courmont
@@ -32,62 +32,62 @@
 #include <fcntl.h>
 
 #include <vlc_common.h>
-#include <vlc_block.h>
+#include <vlc_frame.h>
+#include <vlc_data.h>
 #include <vlc_fs.h>
 
 #ifndef NDEBUG
-static void block_Check (block_t *block)
+static void vlc_frame_Check(vlc_frame_t * frame)
 {
-    while (block != NULL)
+    while (frame != NULL)
     {
-        unsigned char *start = block->p_start;
-        unsigned char *end = block->p_start + block->i_size;
-        unsigned char *bufstart = block->p_buffer;
-        unsigned char *bufend = block->p_buffer + block->i_buffer;
-
+        unsigned char *start = frame->p_start;
+        unsigned char *end = frame->p_start + frame->i_size;
+        unsigned char *bufstart = frame->p_buffer;
+        unsigned char *bufend = frame->p_buffer + frame->i_buffer;
         assert (start <= end);
         assert (bufstart <= bufend);
         assert (bufstart >= start);
         assert (bufend <= end);
-
-        block = block->p_next;
+        frame = frame->p_next;
     }
 }
 #else
-# define block_Check(b) ((void)(b))
+# define vlc_frame_Check(b) ((void)(b))
 #endif
 
-block_t *block_Init(block_t *restrict b, const struct vlc_block_callbacks *cbs,
-                    void *buf, size_t size)
+vlc_frame_t *vlc_frame_Init(vlc_frame_t *restrict f,
+                            const struct vlc_frame_callbacks *cbs,
+                            void *buf, size_t size)
 {
     /* Fill all fields to their default */
-    b->p_next = NULL;
-    b->p_buffer = buf;
-    b->i_buffer = size;
-    b->p_start = buf;
-    b->i_size = size;
-    b->i_flags = 0;
-    b->i_nb_samples = 0;
-    b->i_pts =
-    b->i_dts = VLC_TICK_INVALID;
-    b->i_length = 0;
-    b->cbs = cbs;
-    return b;
+    f->p_next = NULL;
+    f->p_buffer = buf;
+    f->i_buffer = size;
+    f->p_start = buf;
+    f->i_size = size;
+    f->i_flags = 0;
+    f->i_nb_samples = 0;
+    f->i_pts =
+    f->i_dts = VLC_TICK_INVALID;
+    f->i_length = 0;
+    f->cbs = cbs;
+    return f;
 }
 
-static void block_generic_Release (block_t *block)
+static void vlc_frame_generic_Release (vlc_frame_t *frame)
 {
-    /* That is always true for blocks allocated with block_Alloc(). */
-    assert (block->p_start == (unsigned char *)(block + 1));
-    free (block);
+    /* That is always true for frames allocated with vlc_frame_Alloc(). */
+    assert (frame->p_start == (unsigned char *)(frame + 1));
+    free (frame);
 }
 
-static const struct vlc_block_callbacks block_generic_cbs =
+static const struct vlc_frame_callbacks vlc_frame_generic_cbs =
 {
-    block_generic_Release,
+    vlc_frame_generic_Release,
 };
 
-static void BlockMetaCopy( block_t *restrict out, const block_t *in )
+static void FrameMetaCopy( vlc_frame_t *restrict out, const vlc_frame_t *in )
 {
     out->p_next    = in->p_next;
     out->i_nb_samples = in->i_nb_samples;
@@ -97,7 +97,7 @@ static void BlockMetaCopy( block_t *restrict out, const block_t *in )
     out->i_length  = in->i_length;
 }
 
-/** Initial memory alignment of data block.
+/** Initial memory alignment of data frame.
  * @note This must be a multiple of sizeof(void*) and a power of two.
  * libavcodec AVX optimizations require at least 32-bytes. */
 #define BLOCK_ALIGN        32
@@ -105,7 +105,7 @@ static void BlockMetaCopy( block_t *restrict out, const block_t *in )
 /** Initial reserved header and footer size. */
 #define BLOCK_PADDING      32
 
-block_t *block_Alloc (size_t size)
+vlc_frame_t *vlc_frame_Alloc (size_t size)
 {
     if (unlikely(size >> 27))
     {
@@ -114,16 +114,16 @@ block_t *block_Alloc (size_t size)
     }
 
     /* 2 * BLOCK_PADDING: pre + post padding */
-    const size_t alloc = sizeof (block_t) + BLOCK_ALIGN + (2 * BLOCK_PADDING)
+    const size_t alloc = sizeof (vlc_frame_t) + BLOCK_ALIGN + (2 * BLOCK_PADDING)
                        + size;
     if (unlikely(alloc <= size))
         return NULL;
 
-    block_t *b = malloc (alloc);
+    vlc_frame_t *b = malloc (alloc);
     if (unlikely(b == NULL))
         return NULL;
 
-    block_Init(b, &block_generic_cbs, b + 1, alloc - sizeof (*b));
+    vlc_frame_Init(b, &vlc_frame_generic_cbs, b + 1, alloc - sizeof (*b));
     static_assert ((BLOCK_PADDING % BLOCK_ALIGN) == 0,
                    "BLOCK_PADDING must be a multiple of BLOCK_ALIGN");
     b->p_buffer += BLOCK_PADDING + BLOCK_ALIGN - 1;
@@ -132,86 +132,86 @@ block_t *block_Alloc (size_t size)
     return b;
 }
 
-void block_Release(block_t *block)
+void vlc_frame_Release(vlc_frame_t *frame)
 {
 #ifndef NDEBUG
-    block->p_next = NULL;
-    block_Check (block);
+    frame->p_next = NULL;
+    vlc_frame_Check (frame);
 #endif
-    block->cbs->free(block);
+    frame->cbs->free(frame);
 }
 
-block_t *block_TryRealloc (block_t *p_block, ssize_t i_prebody, size_t i_body)
+vlc_frame_t *vlc_frame_TryRealloc (vlc_frame_t *p_frame, ssize_t i_prebody, size_t i_body)
 {
-    block_Check( p_block );
+    vlc_frame_Check( p_frame );
 
-    /* Corner case: empty block requested */
+    /* Corner case: empty frame requested */
     if( i_prebody <= 0 && i_body <= (size_t)(-i_prebody) )
         i_prebody = i_body = 0;
 
-    assert( p_block->p_start <= p_block->p_buffer );
-    assert( p_block->p_start + p_block->i_size
-                                    >= p_block->p_buffer + p_block->i_buffer );
+    assert( p_frame->p_start <= p_frame->p_buffer );
+    assert( p_frame->p_start + p_frame->i_size
+                                    >= p_frame->p_buffer + p_frame->i_buffer );
 
     /* First, shrink payload */
 
     /* Pull payload start */
     if( i_prebody < 0 )
     {
-        if( p_block->i_buffer >= (size_t)-i_prebody )
+        if( p_frame->i_buffer >= (size_t)-i_prebody )
         {
-            p_block->p_buffer -= i_prebody;
-            p_block->i_buffer += i_prebody;
+            p_frame->p_buffer -= i_prebody;
+            p_frame->i_buffer += i_prebody;
         }
         else /* Discard current payload entirely */
-            p_block->i_buffer = 0;
+            p_frame->i_buffer = 0;
         i_body += i_prebody;
         i_prebody = 0;
     }
 
     /* Trim payload end */
-    if( p_block->i_buffer > i_body )
-        p_block->i_buffer = i_body;
+    if( p_frame->i_buffer > i_body )
+        p_frame->i_buffer = i_body;
 
     size_t requested = i_prebody + i_body;
 
-    if( p_block->i_buffer == 0 )
+    if( p_frame->i_buffer == 0 )
     {   /* Corner case: nothing to preserve */
-        if( requested <= p_block->i_size )
+        if( requested <= p_frame->i_size )
         {   /* Enough room: recycle buffer */
-            size_t extra = p_block->i_size - requested;
+            size_t extra = p_frame->i_size - requested;
 
-            p_block->p_buffer = p_block->p_start + (extra / 2);
-            p_block->i_buffer = requested;
-            return p_block;
+            p_frame->p_buffer = p_frame->p_start + (extra / 2);
+            p_frame->i_buffer = requested;
+            return p_frame;
         }
 
         /* Not enough room: allocate a new buffer */
-        block_t *p_rea = block_Alloc( requested );
+        vlc_frame_t *p_rea = vlc_frame_Alloc( requested );
         if( p_rea == NULL )
             return NULL;
 
-        BlockMetaCopy( p_rea, p_block );
-        block_Release( p_block );
+        FrameMetaCopy( p_rea, p_frame );
+        vlc_frame_Release( p_frame );
         return p_rea;
     }
 
-    uint8_t *p_start = p_block->p_start;
-    uint8_t *p_end = p_start + p_block->i_size;
+    uint8_t *p_start = p_frame->p_start;
+    uint8_t *p_end = p_start + p_frame->i_size;
 
     /* Second, reallocate the buffer if we lack space. */
     assert( i_prebody >= 0 );
-    if( (size_t)(p_block->p_buffer - p_start) < (size_t)i_prebody
-     || (size_t)(p_end - p_block->p_buffer) < i_body )
+    if( (size_t)(p_frame->p_buffer - p_start) < (size_t)i_prebody
+     || (size_t)(p_end - p_frame->p_buffer) < i_body )
     {
-        block_t *p_rea = block_Alloc( requested );
+        vlc_frame_t *p_rea = vlc_frame_Alloc( requested );
         if( p_rea == NULL )
             return NULL;
 
-        memcpy( p_rea->p_buffer + i_prebody, p_block->p_buffer,
-                p_block->i_buffer );
-        BlockMetaCopy( p_rea, p_block );
-        block_Release( p_block );
+        memcpy( p_rea->p_buffer + i_prebody, p_frame->p_buffer,
+                p_frame->i_buffer );
+        FrameMetaCopy( p_rea, p_frame );
+        vlc_frame_Release( p_frame );
         return p_rea;
     }
 
@@ -220,64 +220,64 @@ block_t *block_TryRealloc (block_t *p_block, ssize_t i_prebody, size_t i_body)
     /* Push payload start */
     if( i_prebody > 0 )
     {
-        p_block->p_buffer -= i_prebody;
-        p_block->i_buffer += i_prebody;
+        p_frame->p_buffer -= i_prebody;
+        p_frame->i_buffer += i_prebody;
         i_body += i_prebody;
         i_prebody = 0;
     }
 
     /* Expand payload to requested size */
-    p_block->i_buffer = i_body;
+    p_frame->i_buffer = i_body;
 
-    return p_block;
+    return p_frame;
 }
 
-block_t *block_Realloc (block_t *block, ssize_t prebody, size_t body)
+vlc_frame_t *vlc_frame_Realloc (vlc_frame_t *frame, ssize_t prebody, size_t body)
 {
-    block_t *rea = block_TryRealloc (block, prebody, body);
+    vlc_frame_t *rea = vlc_frame_TryRealloc (frame, prebody, body);
     if (rea == NULL)
-        block_Release(block);
+        vlc_frame_Release(frame);
     return rea;
 }
 
-static void block_heap_Release (block_t *block)
+static void vlc_frame_heap_Release (vlc_frame_t *frame)
 {
-    free (block->p_start);
-    free (block);
+    free (frame->p_start);
+    free (frame);
 }
 
-static const struct vlc_block_callbacks block_heap_cbs =
+static const struct vlc_frame_callbacks vlc_frame_heap_cbs =
 {
-    block_heap_Release,
+    vlc_frame_heap_Release,
 };
 
-block_t *block_heap_Alloc (void *addr, size_t length)
+vlc_frame_t *vlc_frame_heap_Alloc (void *addr, size_t length)
 {
-    block_t *block = malloc (sizeof (*block));
-    if (block == NULL)
+    vlc_frame_t *frame = malloc (sizeof (*frame));
+    if (frame == NULL)
     {
         free (addr);
         return NULL;
     }
 
-    return block_Init(block, &block_heap_cbs, addr, length);
+    return vlc_frame_Init(frame, &vlc_frame_heap_cbs, addr, length);
 }
 
 #ifdef HAVE_MMAP
 # include <sys/mman.h>
 
-static void block_mmap_Release (block_t *block)
+static void vlc_frame_mmap_Release (vlc_frame_t *frame)
 {
-    munmap (block->p_start, block->i_size);
-    free (block);
+    munmap (frame->p_start, frame->i_size);
+    free (frame);
 }
 
-static const struct vlc_block_callbacks block_mmap_cbs =
+static const struct vlc_frame_callbacks vlc_frame_mmap_cbs =
 {
-    block_mmap_Release,
+    vlc_frame_mmap_Release,
 };
 
-block_t *block_mmap_Alloc (void *addr, size_t length)
+vlc_frame_t *vlc_frame_mmap_Alloc (void *addr, size_t length)
 {
     if (addr == MAP_FAILED)
         return NULL;
@@ -286,21 +286,21 @@ block_t *block_mmap_Alloc (void *addr, size_t length)
     size_t left = ((uintptr_t)addr) & page_mask;
     size_t right = (-length) & page_mask;
 
-    block_t *block = malloc (sizeof (*block));
-    if (block == NULL)
+    vlc_frame_t *frame = malloc (sizeof (*frame));
+    if (frame == NULL)
     {
         munmap (addr, length);
         return NULL;
     }
 
-    block_Init(block, &block_mmap_cbs,
+    vlc_frame_Init(frame, &vlc_frame_mmap_cbs,
                ((char *)addr) - left, left + length + right);
-    block->p_buffer = addr;
-    block->i_buffer = length;
-    return block;
+    frame->p_buffer = addr;
+    frame->i_buffer = length;
+    return frame;
 }
 #else
-block_t *block_mmap_Alloc (void *addr, size_t length)
+vlc_frame_t *vlc_frame_mmap_Alloc (void *addr, size_t length)
 {
     (void)addr; (void)length; return NULL;
 }
@@ -309,30 +309,30 @@ block_t *block_mmap_Alloc (void *addr, size_t length)
 #ifdef HAVE_SYS_SHM_H
 # include <sys/shm.h>
 
-static void block_shm_Release (block_t *block)
+static void vlc_frame_shm_Release (vlc_frame_t *frame)
 {
-    shmdt(block->p_start);
-    free(block);
+    shmdt(frame->p_start);
+    free(frame);
 }
 
-static const struct vlc_block_callbacks block_shm_cbs =
+static const struct vlc_frame_callbacks vlc_frame_shm_cbs =
 {
-    block_shm_Release,
+    vlc_frame_shm_Release,
 };
 
-block_t *block_shm_Alloc (void *addr, size_t length)
+vlc_frame_t *vlc_frame_shm_Alloc (void *addr, size_t length)
 {
-    block_t *block = malloc (sizeof (*block));
-    if (unlikely(block == NULL))
+    vlc_frame_t *frame = malloc (sizeof (*frame));
+    if (unlikely(frame == NULL))
     {
         shmdt (addr);
         return NULL;
     }
 
-    return block_Init(block, &block_shm_cbs, (uint8_t *)addr, length);
+    return vlc_frame_Init(frame, &vlc_frame_shm_cbs, (uint8_t *)addr, length);
 }
 #else
-block_t *block_shm_Alloc (void *addr, size_t length)
+vlc_frame_t *vlc_frame_shm_Alloc (void *addr, size_t length)
 {
     (void) addr; (void) length;
     abort ();
@@ -361,7 +361,7 @@ ssize_t pread (int fd, void *buf, size_t count, off_t offset)
 }
 #endif
 
-block_t *block_File(int fd, bool write)
+vlc_frame_t *vlc_frame_File(int fd, bool write)
 {
     size_t length;
     struct stat st;
@@ -403,34 +403,34 @@ block_t *block_File(int fd, bool write)
         void *addr = mmap(NULL, length, prot, flags, fd, 0);
 
         if (addr != MAP_FAILED)
-            return block_mmap_Alloc (addr, length);
+            return vlc_frame_mmap_Alloc (addr, length);
     }
 #else
     (void) write;
 #endif
 
     /* If mmap() is not implemented by the OS _or_ the filesystem... */
-    block_t *block = block_Alloc (length);
-    if (block == NULL)
+    vlc_frame_t *frame = vlc_frame_Alloc (length);
+    if (frame == NULL)
         return NULL;
-    block_cleanup_push (block);
+    vlc_frame_cleanup_push (frame);
 
     for (size_t i = 0; i < length;)
     {
-        ssize_t len = pread (fd, block->p_buffer + i, length - i, i);
+        ssize_t len = pread (fd, frame->p_buffer + i, length - i, i);
         if (len == -1)
         {
-            block_Release (block);
-            block = NULL;
+            vlc_frame_Release (frame);
+            frame = NULL;
             break;
         }
         i += len;
     }
     vlc_cleanup_pop ();
-    return block;
+    return frame;
 }
 
-block_t *block_FilePath(const char *path, bool write)
+vlc_frame_t *vlc_frame_FilePath(const char *path, bool write)
 {
     /* NOTE: Writeable shared mappings are not supported here. So there are no
      * needs to open the file for writing (even if the mapping is writable). */
@@ -438,7 +438,7 @@ block_t *block_FilePath(const char *path, bool write)
     if (fd == -1)
         return NULL;
 
-    block_t *block = block_File(fd, write);
+    vlc_frame_t *frame = vlc_frame_File(fd, write);
     vlc_close (fd);
-    return block;
+    return frame;
 }
diff --git a/src/misc/image.c b/src/misc/image.c
index 9d7e5adea0..6e3243a067 100644
--- a/src/misc/image.c
+++ b/src/misc/image.c
@@ -59,13 +59,13 @@ static inline struct decoder_owner *dec_get_owner( decoder_t *p_dec )
     return container_of( p_dec, struct decoder_owner, dec );
 }
 
-static picture_t *ImageRead( image_handler_t *, block_t *,
+static picture_t *ImageRead( image_handler_t *, vlc_frame_t *,
                              const es_format_t *,
                              video_format_t * );
 static picture_t *ImageReadUrl( image_handler_t *, const char *,
                                 video_format_t * );
-static block_t *ImageWrite( image_handler_t *, picture_t *,
-                            const video_format_t *, const video_format_t * );
+static vlc_frame_t *ImageWrite( image_handler_t *, picture_t *,
+                                const video_format_t *, const video_format_t * );
 static int ImageWriteUrl( image_handler_t *, picture_t *,
                           const video_format_t *, const video_format_t *, const char * );
 
@@ -137,7 +137,7 @@ static void ImageQueueVideo( decoder_t *p_dec, picture_t *p_pic )
     picture_fifo_Push( p_owner->p_image->outfifo, p_pic );
 }
 
-static picture_t *ImageRead( image_handler_t *p_image, block_t *p_block,
+static picture_t *ImageRead( image_handler_t *p_image, vlc_frame_t *p_frame,
                              const es_format_t *p_es_in,
                              video_format_t *p_fmt_out )
 {
@@ -145,7 +145,7 @@ static picture_t *ImageRead( image_handler_t *p_image, block_t *p_block,
 
     if ( p_es_in->i_cat != VIDEO_ES )
     {
-        block_Release(p_block);
+        vlc_frame_Release(p_frame);
         return NULL;
     }
 
@@ -163,20 +163,20 @@ static picture_t *ImageRead( image_handler_t *p_image, block_t *p_block,
         p_image->p_dec = CreateDecoder( p_image, p_es_in );
         if( !p_image->p_dec )
         {
-            block_Release(p_block);
+            vlc_frame_Release(p_frame);
             return NULL;
         }
         if( p_image->p_dec->fmt_out.i_cat != VIDEO_ES )
         {
             decoder_Destroy( p_image->p_dec );
             p_image->p_dec = NULL;
-            block_Release(p_block);
+            vlc_frame_Release(p_frame);
             return NULL;
         }
     }
 
-    p_block->i_pts = p_block->i_dts = vlc_tick_now();
-    int ret = p_image->p_dec->pf_decode( p_image->p_dec, p_block );
+    p_frame->i_pts = p_frame->i_dts = vlc_tick_now();
+    int ret = p_image->p_dec->pf_decode( p_image->p_dec, p_frame );
     if( ret == VLCDEC_SUCCESS )
     {
         /* Drain */
@@ -277,7 +277,7 @@ static picture_t *ImageRead( image_handler_t *p_image, block_t *p_block,
 static picture_t *ImageReadUrl( image_handler_t *p_image, const char *psz_url,
                                 video_format_t *p_fmt_out )
 {
-    block_t *p_block;
+    vlc_frame_t *p_frame;
     picture_t *p_pic;
     stream_t *p_stream = NULL;
     uint64_t i_size;
@@ -297,8 +297,8 @@ static picture_t *ImageReadUrl( image_handler_t *p_image, const char *psz_url,
         goto error;
     }
 
-    p_block = vlc_stream_Block( p_stream, i_size );
-    if( p_block == NULL )
+    p_frame = vlc_stream_Frame( p_stream, i_size );
+    if( p_frame == NULL )
         goto error;
 
     vlc_fourcc_t i_chroma = 0;
@@ -318,7 +318,7 @@ static picture_t *ImageReadUrl( image_handler_t *p_image, const char *psz_url,
 
     es_format_t fmtin;
     es_format_Init( &fmtin, VIDEO_ES, i_chroma );
-    p_pic = ImageRead( p_image, p_block, &fmtin, p_fmt_out );
+    p_pic = ImageRead( p_image, p_frame, &fmtin, p_fmt_out );
 
     es_format_Clean( &fmtin );
 
@@ -356,11 +356,11 @@ static bool BitMapFormatIsSimilar( const video_format_t *f1,
  *
  */
 
-static block_t *ImageWrite( image_handler_t *p_image, picture_t *p_pic,
+static vlc_frame_t *ImageWrite( image_handler_t *p_image, picture_t *p_pic,
                             const video_format_t *p_fmt_in,
                             const video_format_t *p_fmt_out )
 {
-    block_t *p_block;
+    vlc_frame_t *p_frame;
 
     /* Check if we can reuse the current encoder */
     if( p_image->p_enc &&
@@ -431,32 +431,32 @@ static block_t *ImageWrite( image_handler_t *p_image, picture_t *p_pic,
 
         if( likely(p_tmp_pic != NULL) )
         {
-            p_block = p_image->p_enc->pf_encode_video( p_image->p_enc,
+            p_frame = p_image->p_enc->pf_encode_video( p_image->p_enc,
                                                        p_tmp_pic );
             picture_Release( p_tmp_pic );
         }
         else
-            p_block = NULL;
+            p_frame = NULL;
     }
     else
     {
-        p_block = p_image->p_enc->pf_encode_video( p_image->p_enc, p_pic );
+        p_frame = p_image->p_enc->pf_encode_video( p_image->p_enc, p_pic );
     }
 
-    if( !p_block )
+    if( !p_frame )
     {
         msg_Dbg( p_image->p_parent, "no image encoded" );
         return 0;
     }
 
-    return p_block;
+    return p_frame;
 }
 
 static int ImageWriteUrl( image_handler_t *p_image, picture_t *p_pic,
                           const video_format_t *p_fmt_in, const video_format_t *p_fmt_out,
                           const char *psz_url )
 {
-    block_t *p_block;
+    vlc_frame_t *p_frame;
     FILE *file;
     video_format_t fmt_out = *p_fmt_out;
 
@@ -473,14 +473,14 @@ static int ImageWriteUrl( image_handler_t *p_image, picture_t *p_pic,
         return VLC_EGENERIC;
     }
 
-    p_block = ImageWrite( p_image, p_pic, p_fmt_in, &fmt_out );
+    p_frame = ImageWrite( p_image, p_pic, p_fmt_in, &fmt_out );
 
     int err = 0;
-    if( p_block )
+    if( p_frame )
     {
-        if( fwrite( p_block->p_buffer, p_block->i_buffer, 1, file ) != 1 )
+        if( fwrite( p_frame->p_buffer, p_frame->i_buffer, 1, file ) != 1 )
             err = errno;
-        block_Release( p_block );
+        vlc_frame_Release( p_frame );
     }
 
     if( fclose( file ) && !err )
diff --git a/src/misc/picture.c b/src/misc/picture.c
index 46a2a069de..8903a9e842 100644
--- a/src/misc/picture.c
+++ b/src/misc/picture.c
@@ -36,7 +36,6 @@
 #include <vlc_common.h>
 #include "picture.h"
 #include <vlc_image.h>
-#include <vlc_block.h>
 
 static void PictureDestroyContext( picture_t *p_picture )
 {
@@ -434,7 +433,7 @@ picture_t *picture_Clone(picture_t *picture)
  *
  *****************************************************************************/
 int picture_Export( vlc_object_t *p_obj,
-                    block_t **pp_image,
+                    vlc_frame_t **pp_image,
                     video_format_t *p_fmt,
                     picture_t *p_picture,
                     vlc_fourcc_t i_format,
@@ -500,19 +499,19 @@ int picture_Export( vlc_object_t *p_obj,
     if( !p_image )
         return VLC_ENOMEM;
 
-    block_t *p_block = image_Write( p_image, p_picture, &fmt_in, &fmt_out );
+    vlc_frame_t *p_frame = image_Write( p_image, p_picture, &fmt_in, &fmt_out );
 
     image_HandlerDelete( p_image );
 
-    if( !p_block )
+    if( !p_frame )
         return VLC_EGENERIC;
 
-    p_block->i_pts =
-    p_block->i_dts = p_picture->date;
+    p_frame->i_pts =
+    p_frame->i_dts = p_picture->date;
 
     if( p_fmt )
         *p_fmt = fmt_out;
-    *pp_image = p_block;
+    *pp_image = p_frame;
 
     return VLC_SUCCESS;
 }
diff --git a/src/missing.c b/src/missing.c
index 4e8b7c9190..1dd64c2ca5 100644
--- a/src/missing.c
+++ b/src/missing.c
@@ -81,9 +81,9 @@ sout_access_out_t *sout_AccessOutNew (vlc_object_t *obj,
     return NULL;
 }
 
-noreturn ssize_t sout_AccessOutRead(sout_access_out_t *out, block_t *block)
+noreturn ssize_t sout_AccessOutRead(sout_access_out_t *out, vlc_frame_t *frame)
 {
-    VLC_UNUSED (out); VLC_UNUSED (block);
+    VLC_UNUSED (out); VLC_UNUSED (frame);
     vlc_assert_unreachable ();
 }
 
@@ -93,9 +93,9 @@ noreturn int sout_AccessOutSeek(sout_access_out_t *out, off_t offset)
     vlc_assert_unreachable ();
 }
 
-noreturn ssize_t sout_AccessOutWrite(sout_access_out_t *out, block_t *block)
+noreturn ssize_t sout_AccessOutWrite(sout_access_out_t *out, vlc_frame_t *frame)
 {
-    VLC_UNUSED (out); VLC_UNUSED (block);
+    VLC_UNUSED (out); VLC_UNUSED (frame);
     vlc_assert_unreachable ();
 }
 
@@ -157,9 +157,9 @@ noreturn sout_mux_t *sout_MuxNew(sout_instance_t *instance, const char *mux,
 }
 
 noreturn int sout_MuxSendBuffer(sout_mux_t *mux, sout_input_t *input,
-                                block_t *block)
+                                vlc_frame_t *frame)
 {
-    VLC_UNUSED (mux); VLC_UNUSED (input); VLC_UNUSED (block);
+    VLC_UNUSED (mux); VLC_UNUSED (input); VLC_UNUSED (frame);
     vlc_assert_unreachable ();
 }
 
diff --git a/src/modules/bank.c b/src/modules/bank.c
index 0b551a91bc..615052e480 100644
--- a/src/modules/bank.c
+++ b/src/modules/bank.c
@@ -44,7 +44,7 @@
 #include <vlc_plugin.h>
 #include <vlc_modules.h>
 #include <vlc_fs.h>
-#include <vlc_block.h>
+#include <vlc_data.h>
 #include "libvlc.h"
 #include "config/configuration.h"
 #include "modules/modules.h"
@@ -94,7 +94,7 @@ static void vlc_modcap_sort(const void *node, const VISIT which,
 static struct
 {
     vlc_mutex_t lock;
-    block_t *caches;
+    vlc_data_t *caches;
     void *caps_tree;
     unsigned usage;
 } modules = { VLC_STATIC_MUTEX, NULL, NULL, 0 };
@@ -617,7 +617,7 @@ void module_InitBank (void)
 void module_EndBank (bool b_plugins)
 {
     vlc_plugin_t *libs = NULL;
-    block_t *caches = NULL;
+    vlc_data_t *caches = NULL;
     void *caps_tree = NULL;
 
     /* If plugins were _not_ loaded, then the caller still has the bank lock
@@ -651,7 +651,7 @@ void module_EndBank (bool b_plugins)
         vlc_plugin_destroy(lib);
     }
 
-    block_ChainRelease(caches);
+    vlc_data_ChainRelease(caches);
 }
 
 #undef module_LoadPlugins
diff --git a/src/modules/cache.c b/src/modules/cache.c
index 4ff76d4267..a4c4d702cb 100644
--- a/src/modules/cache.c
+++ b/src/modules/cache.c
@@ -37,7 +37,7 @@
 #include <assert.h>
 
 #include <vlc_common.h>
-#include <vlc_block.h>
+#include <vlc_data.h>
 #include "libvlc.h"
 
 #include <vlc_plugin.h>
@@ -64,7 +64,7 @@
 #define CACHE_STRING "cache "PACKAGE_NAME" "PACKAGE_VERSION
 
 
-static int vlc_cache_load_immediate(void *out, block_t *in, size_t size)
+static int vlc_cache_load_immediate(void *out, vlc_data_t *in, size_t size)
 {
     if (in->i_buffer < size)
         return -1;
@@ -75,7 +75,7 @@ static int vlc_cache_load_immediate(void *out, block_t *in, size_t size)
     return 0;
 }
 
-static int vlc_cache_load_bool(bool *out, block_t *in)
+static int vlc_cache_load_bool(bool *out, vlc_data_t *in)
 {
     unsigned char b;
 
@@ -87,7 +87,7 @@ static int vlc_cache_load_bool(bool *out, block_t *in)
 }
 
 static int vlc_cache_load_array(const void **p, size_t size, size_t n,
-                                block_t *file)
+                                vlc_data_t *file)
 {
     if (n == 0)
     {
@@ -109,7 +109,7 @@ static int vlc_cache_load_array(const void **p, size_t size, size_t n,
     return 0;
 }
 
-static int vlc_cache_load_string(const char **restrict p, block_t *file)
+static int vlc_cache_load_string(const char **restrict p, vlc_data_t *file)
 {
     uint16_t size;
 
@@ -133,7 +133,7 @@ static int vlc_cache_load_string(const char **restrict p, block_t *file)
     return 0;
 }
 
-static int vlc_cache_load_align(size_t align, block_t *file)
+static int vlc_cache_load_align(size_t align, vlc_data_t *file)
 {
     assert(align > 0);
 
@@ -178,7 +178,7 @@ static int vlc_cache_load_align(size_t align, block_t *file)
     if (vlc_cache_load_align(alignof(t), file)) \
         goto error
 
-static int vlc_cache_load_config(module_config_t *cfg, block_t *file)
+static int vlc_cache_load_config(module_config_t *cfg, vlc_data_t *file)
 {
     LOAD_IMMEDIATE (cfg->i_type);
     LOAD_IMMEDIATE (cfg->i_short);
@@ -242,7 +242,7 @@ error:
     return -1; /* FIXME: leaks */
 }
 
-static int vlc_cache_load_plugin_config(vlc_plugin_t *plugin, block_t *file)
+static int vlc_cache_load_plugin_config(vlc_plugin_t *plugin, vlc_data_t *file)
 {
     uint16_t lines;
 
@@ -286,7 +286,7 @@ error:
     return -1; /* FIXME: leaks */
 }
 
-static int vlc_cache_load_module(vlc_plugin_t *plugin, block_t *file)
+static int vlc_cache_load_module(vlc_plugin_t *plugin, vlc_data_t *file)
 {
     module_t *module = vlc_module_create(plugin);
     if (unlikely(module == NULL))
@@ -316,7 +316,7 @@ error:
     return -1;
 }
 
-static vlc_plugin_t *vlc_cache_load_plugin(block_t *file)
+static vlc_plugin_t *vlc_cache_load_plugin(vlc_data_t *file)
 {
     vlc_plugin_t *plugin = vlc_plugin_create();
     if (unlikely(plugin == NULL))
@@ -366,7 +366,7 @@ error:
  * This allows us to only fully load plugins when they are actually used.
  */
 vlc_plugin_t *vlc_cache_load(vlc_object_t *p_this, const char *dir,
-                             block_t **backingp)
+                             vlc_data_t **backingp)
 {
     char *psz_filename;
 
@@ -377,7 +377,7 @@ vlc_plugin_t *vlc_cache_load(vlc_object_t *p_this, const char *dir,
 
     msg_Dbg( p_this, "loading plugins cache file %s", psz_filename );
 
-    block_t *file = block_FilePath(psz_filename, false);
+    vlc_data_t *file = vlc_data_FilePath(psz_filename, false);
     if (file == NULL)
         msg_Warn(p_this, "cannot read %s: %s", psz_filename,
                  vlc_strerror_c(errno));
@@ -392,7 +392,7 @@ vlc_plugin_t *vlc_cache_load(vlc_object_t *p_this, const char *dir,
      || memcmp(cachestr, CACHE_STRING, sizeof (cachestr)))
     {
         msg_Warn( p_this, "This doesn't look like a valid plugins cache" );
-        block_Release(file);
+        vlc_data_Release(file);
         return NULL;
     }
 
@@ -404,7 +404,7 @@ vlc_plugin_t *vlc_cache_load(vlc_object_t *p_this, const char *dir,
      || memcmp(distrostr, DISTRO_VERSION, sizeof (distrostr)))
     {
         msg_Warn( p_this, "This doesn't look like a valid plugins cache" );
-        block_Release(file);
+        vlc_data_Release(file);
         return NULL;
     }
 #endif
@@ -417,7 +417,7 @@ vlc_plugin_t *vlc_cache_load(vlc_object_t *p_this, const char *dir,
     {
         msg_Warn( p_this, "This doesn't look like a valid plugins cache "
                   "(corrupted header)" );
-        block_Release(file);
+        vlc_data_Release(file);
         return NULL;
     }
 
@@ -432,7 +432,7 @@ vlc_plugin_t *vlc_cache_load(vlc_object_t *p_this, const char *dir,
     {
         msg_Warn( p_this, "This doesn't look like a valid plugins cache "
                   "(corrupted header)" );
-        block_Release(file);
+        vlc_data_Release(file);
         return NULL;
     }
 
@@ -464,7 +464,7 @@ error:
     msg_Warn( p_this, "plugins cache not loaded (corrupted)" );
 
     /* TODO: cleanup */
-    block_Release(file);
+    vlc_data_Release(file);
     return NULL;
 }
 
diff --git a/src/modules/modules.h b/src/modules/modules.h
index 1c7d32e8e5..037efcd03f 100644
--- a/src/modules/modules.h
+++ b/src/modules/modules.h
@@ -161,7 +161,7 @@ void *vlc_dlsym(void *handle, const char *) VLC_USED;
 char *vlc_dlerror(void) VLC_USED;
 
 /* Plugins cache */
-vlc_plugin_t *vlc_cache_load(vlc_object_t *, const char *, block_t **);
+vlc_plugin_t *vlc_cache_load(vlc_object_t *, const char *, vlc_data_t **);
 vlc_plugin_t *vlc_cache_lookup(vlc_plugin_t **, const char *relpath);
 
 void CacheSave(vlc_object_t *, const char *, vlc_plugin_t *const *, size_t);
diff --git a/src/network/httpd.c b/src/network/httpd.c
index 2db57bc174..51f5181e69 100644
--- a/src/network/httpd.c
+++ b/src/network/httpd.c
@@ -41,7 +41,7 @@
 #include <vlc_charset.h>
 #include <vlc_url.h>
 #include <vlc_mime.h>
-#include <vlc_block.h>
+#include <vlc_frame.h>
 #include "../libvlc.h"
 
 #include <string.h>
@@ -599,10 +599,10 @@ struct httpd_stream_t
     uint8_t *p_header;
     int     i_header;
 
-    /* Some muxes, in particular the avformat mux, can mark given blocks
+    /* Some muxes, in particular the avformat mux, can mark given frames
      * as keyframes, to ensure that the stream starts with one.
      * (This is particularly important for WebM streaming to certain
-     * browsers.) Store if we've ever seen any such keyframe blocks,
+     * browsers.) Store if we've ever seen any such keyframe frames,
      * and if so, the byte position of the start of the last one. */
     bool        b_has_keyframes;
     int64_t     i_last_keyframe_seen_pos;
@@ -819,9 +819,9 @@ static void httpd_AppendData(httpd_stream_t *stream, uint8_t *p_data, int i_data
     stream->i_buffer_pos += i_data;
 }
 
-int httpd_StreamSend(httpd_stream_t *stream, const block_t *p_block)
+int httpd_StreamSend(httpd_stream_t *stream, const vlc_frame_t *p_frame)
 {
-    if (!p_block || !p_block->p_buffer)
+    if (!p_frame || !p_frame->p_buffer)
         return VLC_SUCCESS;
 
     vlc_mutex_lock(&stream->lock);
@@ -829,12 +829,12 @@ int httpd_StreamSend(httpd_stream_t *stream, const block_t *p_block)
     /* save this pointer (to be used by new connection) */
     stream->i_buffer_last_pos = stream->i_buffer_pos;
 
-    if (p_block->i_flags & BLOCK_FLAG_TYPE_I) {
+    if (p_frame->i_flags & FRAME_FLAG_TYPE_I) {
         stream->b_has_keyframes = true;
         stream->i_last_keyframe_seen_pos = stream->i_buffer_pos;
     }
 
-    httpd_AppendData(stream, p_block->p_buffer, p_block->i_buffer);
+    httpd_AppendData(stream, p_frame->p_buffer, p_frame->i_buffer);
 
     vlc_mutex_unlock(&stream->lock);
     return VLC_SUCCESS;
diff --git a/src/stream_output/stream_output.c b/src/stream_output/stream_output.c
index 4c8bba8b5e..035c6e0677 100644
--- a/src/stream_output/stream_output.c
+++ b/src/stream_output/stream_output.c
@@ -43,7 +43,7 @@
 #include "stream_output.h"
 
 #include <vlc_meta.h>
-#include <vlc_block.h>
+#include <vlc_frame.h>
 #include <vlc_codec.h>
 #include <vlc_modules.h>
 
@@ -258,14 +258,14 @@ void sout_InputFlush( sout_packetizer_input_t *p_input )
  *
  *****************************************************************************/
 int sout_InputSendBuffer( sout_packetizer_input_t *p_input,
-                          block_t *p_buffer )
+                          vlc_frame_t *p_buffer )
 {
     sout_instance_t     *p_sout = p_input->p_sout;
     int                 i_ret;
 
     if( p_input->b_flushed )
     {
-        p_buffer->i_flags |= BLOCK_FLAG_DISCONTINUITY;
+        p_buffer->i_flags |= FRAME_FLAG_DISCONTINUITY;
         p_input->b_flushed = false;
     }
     vlc_mutex_lock( &p_sout->lock );
@@ -347,7 +347,7 @@ int sout_AccessOutSeek( sout_access_out_t *p_access, off_t i_pos )
 /*****************************************************************************
  * sout_AccessRead:
  *****************************************************************************/
-ssize_t sout_AccessOutRead( sout_access_out_t *p_access, block_t *p_buffer )
+ssize_t sout_AccessOutRead( sout_access_out_t *p_access, vlc_frame_t *p_buffer )
 {
     return( p_access->pf_read ?
             p_access->pf_read( p_access, p_buffer ) : VLC_EGENERIC );
@@ -356,7 +356,7 @@ ssize_t sout_AccessOutRead( sout_access_out_t *p_access, block_t *p_buffer )
 /*****************************************************************************
  * sout_AccessWrite:
  *****************************************************************************/
-ssize_t sout_AccessOutWrite( sout_access_out_t *p_access, block_t *p_buffer )
+ssize_t sout_AccessOutWrite( sout_access_out_t *p_access, vlc_frame_t *p_buffer )
 {
     return p_access->pf_write( p_access, p_buffer );
 }
@@ -503,7 +503,7 @@ sout_input_t *sout_MuxAddStream( sout_mux_t *p_mux, const es_format_t *p_fmt )
     es_format_Copy( &p_input->fmt, p_fmt );
     p_input->p_fmt = &p_input->fmt;
 
-    p_input->p_fifo = block_FifoNew();
+    p_input->p_fifo = vlc_frame_FifoNew();
     p_input->p_sys  = NULL;
 
     TAB_APPEND( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input );
@@ -511,7 +511,7 @@ sout_input_t *sout_MuxAddStream( sout_mux_t *p_mux, const es_format_t *p_fmt )
     {
         msg_Err( p_mux, "cannot add this stream" );
         TAB_REMOVE( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input );
-        block_FifoRelease( p_input->p_fifo );
+        vlc_frame_FifoRelease( p_input->p_fifo );
         es_format_Clean( &p_input->fmt );
         free( p_input );
         return NULL;
@@ -528,7 +528,7 @@ void sout_MuxDeleteStream( sout_mux_t *p_mux, sout_input_t *p_input )
     int i_index;
 
     if( p_mux->b_waiting_stream
-     && block_FifoCount( p_input->p_fifo ) > 0 )
+     && vlc_frame_FifoCount( p_input->p_fifo ) > 0 )
     {
         /* We stop waiting, and call the muxer for taking care of the data
          * before we remove this es */
@@ -549,7 +549,7 @@ void sout_MuxDeleteStream( sout_mux_t *p_mux, sout_input_t *p_input )
             msg_Warn( p_mux, "no more input streams for this mux" );
         }
 
-        block_FifoRelease( p_input->p_fifo );
+        vlc_frame_FifoRelease( p_input->p_fifo );
         es_format_Clean( &p_input->fmt );
         free( p_input );
     }
@@ -559,10 +559,10 @@ void sout_MuxDeleteStream( sout_mux_t *p_mux, sout_input_t *p_input )
  * sout_MuxSendBuffer:
  *****************************************************************************/
 int sout_MuxSendBuffer( sout_mux_t *p_mux, sout_input_t *p_input,
-                         block_t *p_buffer )
+                         vlc_frame_t *p_buffer )
 {
     vlc_tick_t i_dts = p_buffer->i_dts;
-    block_FifoPut( p_input->p_fifo, p_buffer );
+    vlc_frame_FifoPut( p_input->p_fifo, p_buffer );
 
     if( p_mux->p_sout->i_out_pace_nocontrol )
     {
@@ -593,25 +593,25 @@ int sout_MuxSendBuffer( sout_mux_t *p_mux, sout_input_t *p_input,
 void sout_MuxFlush( sout_mux_t *p_mux, sout_input_t *p_input )
 {
     VLC_UNUSED(p_mux);
-    block_FifoEmpty( p_input->p_fifo );
+    vlc_frame_FifoEmpty( p_input->p_fifo );
 }
 
 /*****************************************************************************
  * sout_MuxGetStream: find stream to be muxed
  *****************************************************************************/
-int sout_MuxGetStream( sout_mux_t *p_mux, unsigned i_blocks, vlc_tick_t *pi_dts )
+int sout_MuxGetStream( sout_mux_t *p_mux, unsigned i_frames, vlc_tick_t *pi_dts )
 {
     vlc_tick_t i_dts = 0;
     int     i_stream = -1;
 
-    assert( i_blocks > 0 );
+    assert( i_frames > 0 );
 
     for( int i = 0; i < p_mux->i_nb_inputs; i++ )
     {
         sout_input_t *p_input = p_mux->pp_inputs[i];
-        block_t *p_data;
+        vlc_frame_t *p_data;
 
-        if( block_FifoCount( p_input->p_fifo ) < i_blocks )
+        if( vlc_frame_FifoCount( p_input->p_fifo ) < i_frames )
         {
             if( (!p_mux->b_add_stream_any_time) &&
                 (p_input->p_fmt->i_cat != SPU_ES ) )
@@ -622,7 +622,7 @@ int sout_MuxGetStream( sout_mux_t *p_mux, unsigned i_blocks, vlc_tick_t *pi_dts
             continue;
         }
 
-        p_data = block_FifoShow( p_input->p_fifo );
+        p_data = vlc_frame_FifoShow( p_input->p_fifo );
         if( i_stream < 0 || p_data->i_dts < i_dts )
         {
             i_stream = i;
diff --git a/src/stream_output/stream_output.h b/src/stream_output/stream_output.h
index 84e5426ded..bfb479c0d7 100644
--- a/src/stream_output/stream_output.h
+++ b/src/stream_output/stream_output.h
@@ -46,7 +46,7 @@ void sout_DeleteInstance( sout_instance_t * );
 
 sout_packetizer_input_t *sout_InputNew( sout_instance_t *, const es_format_t * );
 int sout_InputDelete( sout_packetizer_input_t * );
-int sout_InputSendBuffer( sout_packetizer_input_t *, block_t* );
+int sout_InputSendBuffer( sout_packetizer_input_t *, vlc_frame_t* );
 bool sout_InputIsEmpty(sout_packetizer_input_t *);
 
 enum sout_input_query_e
diff --git a/src/test/block_test.c b/src/test/block_test.c
index 5c1a6b00d3..36a185ea01 100644
--- a/src/test/block_test.c
+++ b/src/test/block_test.c
@@ -28,13 +28,14 @@
 #include <assert.h>
 
 #include <vlc_common.h>
-#include <vlc_block.h>
+#include <vlc_frame.h>
+#include <vlc_data.h>
 
 static const char text[] =
     "This is a test!\n"
     "This file can be deleted safely!\n";
 
-static void test_block_File(bool write)
+static void test_vlc_frame_File(bool write)
 {
     FILE *stream;
     int res;
@@ -47,50 +48,106 @@ static void test_block_File(bool write)
     res = fflush (stream);
     assert (res != EOF);
 
-    block_t *block = block_File(fileno(stream), write);
+    vlc_frame_t *frame = vlc_frame_File(fileno(stream), write);
     fclose (stream);
 
-    assert (block != NULL);
-    assert (block->i_buffer == strlen (text));
-    assert (!memcmp (block->p_buffer, text, block->i_buffer));
+    assert (frame != NULL);
+    assert (frame->i_buffer == strlen (text));
+    assert (!memcmp (frame->p_buffer, text, frame->i_buffer));
     if (write)
-        memset(block->p_buffer, 'A', block->i_buffer);
-    block_Release (block);
+        memset(frame->p_buffer, 'A', frame->i_buffer);
+    vlc_frame_Release (frame);
 
     remove ("testfile.txt");
 }
 
-static void test_block (void)
+static void test_frame (void)
 {
-    block_t *block = block_Alloc (sizeof (text));
-    assert (block != NULL);
-
-    memcpy (block->p_buffer, text, sizeof (text));
-    block = block_Realloc (block, 0, sizeof (text));
-    assert (block != NULL);
-    assert (block->i_buffer == sizeof (text));
-    assert (!memcmp (block->p_buffer, text, sizeof (text)));
-
-    block = block_Realloc (block, 200, sizeof (text) + 200);
-    assert (block != NULL);
-    assert (block->i_buffer == 200 + sizeof (text) + 200);
-    assert (!memcmp (block->p_buffer + 200, text, sizeof (text)));
-
-    block = block_Realloc (block, -200, sizeof (text) + 200);
-    assert (block != NULL);
-    assert (block->i_buffer == sizeof (text));
-    assert (!memcmp (block->p_buffer, text, sizeof (text)));
-    block_Release (block);
-
-    //block = block_Alloc (SIZE_MAX);
-    //assert (block == NULL);
+    vlc_frame_t *frame = vlc_frame_Alloc (sizeof (text));
+    assert (frame != NULL);
+
+    memcpy (frame->p_buffer, text, sizeof (text));
+    frame = vlc_frame_Realloc (frame, 0, sizeof (text));
+    assert (frame != NULL);
+    assert (frame->i_buffer == sizeof (text));
+    assert (!memcmp (frame->p_buffer, text, sizeof (text)));
+
+    frame = vlc_frame_Realloc (frame, 200, sizeof (text) + 200);
+    assert (frame != NULL);
+    assert (frame->i_buffer == 200 + sizeof (text) + 200);
+    assert (!memcmp (frame->p_buffer + 200, text, sizeof (text)));
+
+    frame = vlc_frame_Realloc (frame, -200, sizeof (text) + 200);
+    assert (frame != NULL);
+    assert (frame->i_buffer == sizeof (text));
+    assert (!memcmp (frame->p_buffer, text, sizeof (text)));
+    vlc_frame_Release (frame);
+
+    //frame = vlc_frame_Alloc (SIZE_MAX);
+    //assert (frame == NULL);
 }
 
+static void test_vlc_data_File(bool write)
+{
+    FILE *stream;
+    int res;
+
+    stream = fopen ("testfile.txt", "wb+e");
+    assert (stream != NULL);
+
+    res = fputs (text, stream);
+    assert (res != EOF);
+    res = fflush (stream);
+    assert (res != EOF);
+
+    vlc_data_t *data = vlc_data_File(fileno(stream), write);
+    fclose (stream);
+
+    assert (data != NULL);
+    assert (data->i_buffer == strlen (text));
+    assert (!memcmp (data->p_buffer, text, data->i_buffer));
+    if (write)
+        memset(data->p_buffer, 'A', data->i_buffer);
+    vlc_data_Release (data);
+
+    remove ("testfile.txt");
+}
+
+static void test_data (void)
+{
+    vlc_data_t *data = vlc_data_Alloc (sizeof (text));
+    assert (data != NULL);
+
+    memcpy (data->p_buffer, text, sizeof (text));
+    data = vlc_data_Realloc (data, 0, sizeof (text));
+    assert (data != NULL);
+    assert (data->i_buffer == sizeof (text));
+    assert (!memcmp (data->p_buffer, text, sizeof (text)));
+
+    data = vlc_data_Realloc (data, 200, sizeof (text) + 200);
+    assert (data != NULL);
+    assert (data->i_buffer == 200 + sizeof (text) + 200);
+    assert (!memcmp (data->p_buffer + 200, text, sizeof (text)));
+
+    data = vlc_data_Realloc (data, -200, sizeof (text) + 200);
+    assert (data != NULL);
+    assert (data->i_buffer == sizeof (text));
+    assert (!memcmp (data->p_buffer, text, sizeof (text)));
+    vlc_data_Release (data);
+
+    //data = vlc_data_Alloc (SIZE_MAX);
+    //assert (data == NULL);
+}
+
+
 int main (void)
 {
-    test_block_File(false);
-    test_block_File(true);
-    test_block ();
+    test_vlc_frame_File(false);
+    test_vlc_frame_File(true);
+    test_frame ();
+    test_vlc_data_File(false);
+    test_vlc_data_File(true);
+    test_data ();
     return 0;
 }
 
diff --git a/src/video_output/display.c b/src/video_output/display.c
index e5c072ae2a..554e9ed0bf 100644
--- a/src/video_output/display.c
+++ b/src/video_output/display.c
@@ -32,7 +32,6 @@
 #include <vlc_common.h>
 #include <vlc_vout_display.h>
 #include <vlc_vout.h>
-#include <vlc_block.h>
 #include <vlc_modules.h>
 #include <vlc_filter.h>
 #include <vlc_picture_pool.h>
diff --git a/src/video_output/snapshot.c b/src/video_output/snapshot.c
index 92b5886dc8..0e5814b433 100644
--- a/src/video_output/snapshot.c
+++ b/src/video_output/snapshot.c
@@ -34,7 +34,7 @@
 #include <vlc_common.h>
 #include <vlc_fs.h>
 #include <vlc_strings.h>
-#include <vlc_block.h>
+#include <vlc_frame.h>
 #include <vlc_vout.h>
 
 #include "snapshot.h"
@@ -169,7 +169,7 @@ char *vout_snapshot_GetDirectory(void)
 }
 /* */
 int vout_snapshot_SaveImage(char **name, int *sequential,
-                             const block_t *image,
+                             const vlc_frame_t *image,
                              vout_thread_t *p_vout,
                              const vout_snapshot_save_cfg_t *cfg)
 {
diff --git a/src/video_output/snapshot.h b/src/video_output/snapshot.h
index 1c3678ccdc..b6e125be39 100644
--- a/src/video_output/snapshot.h
+++ b/src/video_output/snapshot.h
@@ -67,7 +67,7 @@ typedef struct {
  * This function will write an image to the disk an return the file name created.
  */
 int vout_snapshot_SaveImage(char **name, int *sequential,
-                            const block_t *image,
+                            const vlc_frame_t *image,
                             vout_thread_t *p_vout,
                             const vout_snapshot_save_cfg_t *cfg);
 
diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index 9604522825..938de58007 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -332,7 +332,7 @@ void vout_PutPicture(vout_thread_t *vout, picture_t *picture)
 
 /* */
 int vout_GetSnapshot(vout_thread_t *vout,
-                     block_t **image_dst, picture_t **picture_dst,
+                     vlc_frame_t **image_dst, picture_t **picture_dst,
                      video_format_t *fmt,
                      const char *type, vlc_tick_t timeout)
 {
diff --git a/src/video_output/vout_intf.c b/src/video_output/vout_intf.c
index 260c160ab4..d3995fb650 100644
--- a/src/video_output/vout_intf.c
+++ b/src/video_output/vout_intf.c
@@ -34,7 +34,7 @@
 #include <stdlib.h>                                                /* free() */
 #include <assert.h>
 
-#include <vlc_block.h>
+#include <vlc_frame.h>
 #include <vlc_modules.h>
 
 #include <vlc_vout.h>
@@ -388,7 +388,7 @@ static void VoutSaveSnapshot( vout_thread_t *p_vout )
 
     /* */
     picture_t *p_picture;
-    block_t *p_image;
+    vlc_frame_t *p_image;
 
     /* 500ms timeout
      * XXX it will cause trouble with low fps video (< 2fps) */
@@ -434,7 +434,7 @@ static void VoutSaveSnapshot( vout_thread_t *p_vout )
 
 exit:
     if( p_image )
-        block_Release( p_image );
+        vlc_frame_Release( p_image );
     if( p_picture )
         picture_Release( p_picture );
     free( psz_prefix );
diff --git a/test/modules/packetizer/helpers.c b/test/modules/packetizer/helpers.c
index 0ef5e5db48..5ad21a4dd3 100644
--- a/test/modules/packetizer/helpers.c
+++ b/test/modules/packetizer/helpers.c
@@ -26,8 +26,8 @@
 #include <assert.h>
 
 #include <vlc_common.h>
-#include <vlc_block.h>
-#include <vlc_block_helper.h>
+#include <vlc_frame.h>
+#include <vlc_frame_helper.h>
 
 #include "../modules/packetizer/startcode_helper.h"
 
diff --git a/test/modules/packetizer/hxxx.c b/test/modules/packetizer/hxxx.c
index 6a7767570f..f2eb4f754b 100644
--- a/test/modules/packetizer/hxxx.c
+++ b/test/modules/packetizer/hxxx.c
@@ -28,7 +28,7 @@
 
 #include <assert.h>
 #include <vlc_common.h>
-#include <vlc_block.h>
+#include <vlc_frame.h>
 #include "../modules/packetizer/hxxx_nal.h"
 #include "../modules/packetizer/hxxx_nal.c"
 
@@ -92,7 +92,7 @@ static void testannexbin( const uint8_t *p_data, size_t i_data,
 
     for( unsigned int i=0; i<3; i++)
     {
-        block_t *p_block = block_Alloc( i_data );
+        vlc_frame_t *p_block = vlc_frame_Alloc( i_data );
         memcpy( p_block->p_buffer, p_data, i_data );
 
         p_block = hxxx_AnnexB_to_xVC( p_block, 1 << i );
@@ -110,7 +110,7 @@ static void testannexbin( const uint8_t *p_data, size_t i_data,
 
             assert( p_block->i_buffer == pi_res[i] );
             assert( memcmp( p_block->p_buffer, pp_res[i], pi_res[i] ) == 0 );
-            block_Release( p_block );
+            vlc_frame_Release( p_block );
         }
         else
         {
diff --git a/test/src/input/decoder.c b/test/src/input/decoder.c
index 5773996b3f..93c25251c1 100644
--- a/test/src/input/decoder.c
+++ b/test/src/input/decoder.c
@@ -68,15 +68,15 @@ static void queue_video(decoder_t *dec, picture_t *pic)
     picture_Release(pic);
 }
 
-static void queue_audio(decoder_t *dec, block_t *p_block)
+static void queue_audio(decoder_t *dec, vlc_frame_t *p_block)
 {
     (void) dec;
-    block_Release(p_block);
+    vlc_frame_Release(p_block);
 }
-static void queue_cc(decoder_t *dec, block_t *p_block, const decoder_cc_desc_t *desc)
+static void queue_cc(decoder_t *dec, vlc_frame_t *p_block, const decoder_cc_desc_t *desc)
 {
     (void) dec; (void) desc;
-    block_Release(p_block);
+    vlc_frame_Release(p_block);
 }
 static void queue_sub(decoder_t *dec, subpicture_t *p_subpic)
 {
@@ -194,7 +194,7 @@ decoder_t *test_decoder_create(vlc_object_t *parent, const es_format_t *fmt)
     return decoder;
 }
 
-int test_decoder_process(decoder_t *decoder, block_t *p_block)
+int test_decoder_process(decoder_t *decoder, vlc_frame_t *p_block)
 {
     struct decoder_owner *owner = dec_get_owner(decoder);
     decoder_t *packetizer = owner->packetizer;
@@ -203,12 +203,12 @@ int test_decoder_process(decoder_t *decoder, block_t *p_block)
     if (decoder->p_module == NULL)
     {
         if (p_block != NULL)
-            block_Release(p_block);
+            vlc_frame_Release(p_block);
         return VLC_EGENERIC;
     }
 
-    block_t **pp_block = p_block ? &p_block : NULL;
-    block_t *p_packetized_block;
+    vlc_frame_t **pp_block = p_block ? &p_block : NULL;
+    vlc_frame_t *p_packetized_block;
     while ((p_packetized_block =
                 packetizer->pf_packetize(packetizer, pp_block)))
     {
@@ -224,7 +224,7 @@ int test_decoder_process(decoder_t *decoder, block_t *p_block)
             decoder_Clean(decoder);
             if (decoder_load(decoder, false, &packetizer->fmt_out) != VLC_SUCCESS)
             {
-                block_ChainRelease(p_packetized_block);
+                vlc_frame_ChainRelease(p_packetized_block);
                 return VLC_EGENERIC;
             }
         }
@@ -232,22 +232,22 @@ int test_decoder_process(decoder_t *decoder, block_t *p_block)
         if (packetizer->pf_get_cc)
         {
             decoder_cc_desc_t desc;
-            block_t *p_cc = packetizer->pf_get_cc(packetizer, &desc);
+            vlc_frame_t *p_cc = packetizer->pf_get_cc(packetizer, &desc);
             if (p_cc)
-                block_Release(p_cc);
+                vlc_frame_Release(p_cc);
         }
 
         while (p_packetized_block != NULL)
         {
 
-            block_t *p_next = p_packetized_block->p_next;
+            vlc_frame_t *p_next = p_packetized_block->p_next;
             p_packetized_block->p_next = NULL;
 
             int ret = decoder->pf_decode(decoder, p_packetized_block);
 
             if (ret == VLCDEC_ECRITICAL)
             {
-                block_ChainRelease(p_next);
+                vlc_frame_ChainRelease(p_next);
                 return VLC_EGENERIC;
             }
 
diff --git a/test/src/input/decoder.h b/test/src/input/decoder.h
index 2c64d6f14d..96acd9018f 100644
--- a/test/src/input/decoder.h
+++ b/test/src/input/decoder.h
@@ -22,4 +22,4 @@
 
 decoder_t *test_decoder_create(vlc_object_t *parent, const es_format_t *fmt);
 void test_decoder_destroy(decoder_t *decoder);
-int test_decoder_process(decoder_t *decoder, block_t *block);
+int test_decoder_process(decoder_t *decoder, vlc_frame_t *block);
diff --git a/test/src/input/demux-run.c b/test/src/input/demux-run.c
index 8178756ed6..4c8a1946ef 100644
--- a/test/src/input/demux-run.c
+++ b/test/src/input/demux-run.c
@@ -100,7 +100,7 @@ static void EsOutCheckId(struct test_es_out_t *ctx, es_out_id_t *id)
     abort();
 }
 
-static int EsOutSend(es_out_t *out, es_out_id_t *id, block_t *block)
+static int EsOutSend(es_out_t *out, es_out_id_t *id, vlc_frame_t *block)
 {
     struct test_es_out_t *ctx = (struct test_es_out_t *) out;
 
@@ -111,7 +111,7 @@ static int EsOutSend(es_out_t *out, es_out_id_t *id, block_t *block)
         test_decoder_process(id->decoder, block);
     else
 #endif
-        block_Release(block);
+        vlc_frame_Release(block);
     return VLC_SUCCESS;
 }
 
diff --git a/test/src/input/stream_fifo.c b/test/src/input/stream_fifo.c
index b725467df7..f69a591398 100644
--- a/test/src/input/stream_fifo.c
+++ b/test/src/input/stream_fifo.c
@@ -42,7 +42,7 @@ static stream_t *reader;
 
 int main(void)
 {
-    block_t *block;
+    vlc_data_t *block;
     const unsigned char *peek;
     ssize_t val;
     char buf[16];
@@ -152,7 +152,7 @@ int main(void)
     assert(block->i_buffer <= 30);
     assert(memcmp(block->p_buffer, "1st block\n2nd block\n3rd block\n",
                   block->i_buffer) == 0);
-    block_Release(block);
+    vlc_data_Release(block);
 
     block = vlc_stream_ReadBlock(reader);
     assert(block == NULL);
@@ -178,7 +178,7 @@ int main(void)
     assert(vlc_stream_Tell(reader) == 10);
     assert(block->i_buffer == 10);
     assert(memcmp(block->p_buffer, "1st block\n", 10) == 0);
-    block_Release(block);
+    vlc_data_Release(block);
 
     val = vlc_stream_Read(reader, buf, 5);
     assert(val == 5);
@@ -213,19 +213,19 @@ int main(void)
     assert(!vlc_stream_Eof(reader));
     assert(memcmp(peek, "bl", 2) == 0);
 
-    block = vlc_stream_Block(reader, 3);
-    assert(block != NULL);
-    assert(block->i_buffer == 3);
+    vlc_frame_t * frame = vlc_stream_Frame(reader, 3);
+    assert(frame != NULL);
+    assert(frame->i_buffer == 3);
     assert(vlc_stream_Tell(reader) == 27);
-    assert(memcmp(block->p_buffer, "blo", 3) == 0);
-    block_Release(block);
+    assert(memcmp(frame->p_buffer, "blo", 3) == 0);
+    vlc_frame_Release(frame);
 
     block = vlc_stream_ReadBlock(reader);
     assert(block != NULL);
     assert(block->i_buffer == 3);
     assert(vlc_stream_Tell(reader) == 30);
     assert(memcmp(block->p_buffer, "ck\n", 3) == 0);
-    block_Release(block);
+    vlc_data_Release(block);
 
     val = vlc_stream_Read(reader, buf, 5);
     assert(val == 5);
@@ -239,7 +239,7 @@ int main(void)
     assert(vlc_stream_Tell(reader) == 40);
     assert(memcmp(block->p_buffer, "lock\n", 5) == 0);
     vlc_stream_Delete(reader);
-    block_Release(block);
+    vlc_data_Release(block);
 
     libvlc_release(vlc);
 
-- 
2.20.1



More information about the vlc-devel mailing list