]> git.sesse.net Git - vlc/blobdiff - modules/demux/asf/asf.c
* Stringreview !!!
[vlc] / modules / demux / asf / asf.c
index 6118a23a97e542e3a5fde15b2b5a6a1a6b79fbfb..8262b1d5d1ee9f232e2070b268acbd7a2e55df33 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
- * asf.c : ASFv01 file input module for vlc
+ * asf.c : ASF demux module
  *****************************************************************************
  * Copyright (C) 2002-2003 VideoLAN
- * $Id: asf.c,v 1.36 2003/08/25 23:36:16 fenrir Exp $
+ * $Id: asf.c,v 1.49 2004/01/25 20:05:28 hartman Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
@@ -28,7 +28,8 @@
 
 #include <vlc/vlc.h>
 #include <vlc/input.h>
-#include "ninput.h"
+
+#include "vlc_playlist.h"
 
 #include "codecs.h"                        /* BITMAPINFOHEADER, WAVEFORMATEX */
 #include "libasf.h"
@@ -55,12 +56,14 @@ static int  Demux   ( input_thread_t * );
 typedef struct asf_stream_s
 {
     int i_cat;
-    es_descriptor_t *p_es;
+
+    es_out_id_t     *p_es;
+
     asf_object_stream_properties_t *p_sp;
 
     mtime_t i_time;
 
-    pes_packet_t    *p_pes;     /* used to keep uncomplete frames */
+    block_t         *p_frame; /* use to gather complete frame */
 
 } asf_stream_t;
 
@@ -77,8 +80,6 @@ struct demux_sys_t
 
     int64_t             i_data_begin;
     int64_t             i_data_end;
-
-    stream_t            *s;
 };
 
 static mtime_t  GetMoviePTS( demux_sys_t * );
@@ -95,8 +96,7 @@ static int Open( vlc_object_t * p_this )
     guid_t          guid;
 
     demux_sys_t     *p_sys;
-    unsigned int    i_stream;
-    unsigned int    i;
+    unsigned int    i_stream, i;
     asf_object_content_description_t *p_cd;
 
     vlc_bool_t      b_seekable;
@@ -117,26 +117,18 @@ static int Open( vlc_object_t * p_this )
     }
 
     /* Set p_input field */
-    p_input->pf_demux = Demux;
+    p_input->pf_demux         = Demux;
+    p_input->pf_demux_control = demux_vaControlDefault;
     p_input->p_demux_data = p_sys = malloc( sizeof( demux_sys_t ) );
     memset( p_sys, 0, sizeof( demux_sys_t ) );
     p_sys->i_time = -1;
     p_sys->i_length = 0;
 
-    /* Create stream facilities */
-    if( ( p_sys->s = stream_OpenInput( p_input ) ) == NULL )
-    {
-        msg_Err( p_input, "cannot create stream" );
-        free( p_sys );
-        return VLC_EGENERIC;
-    }
-
     /* Now load all object ( except raw data ) */
-    stream_Control( p_sys->s, STREAM_CAN_FASTSEEK, &b_seekable );
-    if( (p_sys->p_root = ASF_ReadObjectRoot( p_sys->s, b_seekable )) == NULL )
+    stream_Control( p_input->s, STREAM_CAN_FASTSEEK, &b_seekable );
+    if( (p_sys->p_root = ASF_ReadObjectRoot( p_input->s, b_seekable )) == NULL )
     {
         msg_Warn( p_input, "ASF plugin discarded (not a valid file)" );
-        stream_Release( p_sys->s );
         free( p_sys );
         return VLC_EGENERIC;
     }
@@ -159,7 +151,6 @@ static int Open( vlc_object_t * p_this )
 
     msg_Dbg( p_input, "found %d streams", p_sys->i_streams );
 
-    /*  create one program */
     vlc_mutex_lock( &p_input->stream.stream_lock );
     if( input_InitStream( p_input, 0 ) == -1)
     {
@@ -167,13 +158,6 @@ static int Open( vlc_object_t * p_this )
         msg_Err( p_input, "cannot init stream" );
         goto error;
     }
-    if( input_AddProgram( p_input, 0, 0) == NULL )
-    {
-        vlc_mutex_unlock( &p_input->stream.stream_lock );
-        msg_Err( p_input, "cannot add program" );
-        goto error;
-    }
-    p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
     p_input->stream.i_mux_rate = 0 ; /* updated later */
     vlc_mutex_unlock( &p_input->stream.stream_lock );
 
@@ -194,110 +178,61 @@ static int Open( vlc_object_t * p_this )
         p_stream->i_time = -1;
         p_stream->p_sp = p_sp;
         p_stream->p_es = NULL;
+        p_stream->p_frame = NULL;
 
-        if( ASF_CmpGUID( &p_sp->i_stream_type, &asf_object_stream_type_audio ) )
+        if( ASF_CmpGUID( &p_sp->i_stream_type, &asf_object_stream_type_audio ) &&
+            p_sp->i_type_specific_data_length >= sizeof( WAVEFORMATEX ) - 2 )
         {
-            int i_codec;
-            if( p_sp->p_type_specific_data )
-            {
-                i_codec = GetWLE( p_sp->p_type_specific_data );
-            }
-            else
+            es_format_t  fmt;
+            uint8_t      *p_data = p_sp->p_type_specific_data;
+
+            es_format_Init( &fmt, AUDIO_ES, 0 );
+            wf_tag_to_fourcc( GetWLE( &p_data[0] ), &fmt.i_codec, NULL );
+            fmt.audio.i_channels        = GetWLE(  &p_data[2] );
+            fmt.audio.i_rate      = GetDWLE( &p_data[4] );
+            fmt.i_bitrate         = GetDWLE( &p_data[8] ) * 8;
+            fmt.audio.i_blockalign      = GetWLE(  &p_data[12] );
+            fmt.audio.i_bitspersample   = GetWLE(  &p_data[14] );
+
+            if( p_sp->i_type_specific_data_length > sizeof( WAVEFORMATEX ) )
             {
-                i_codec = -1;
+                fmt.i_extra = __MIN( GetWLE( &p_data[16] ),
+                                     p_sp->i_type_specific_data_length - sizeof( WAVEFORMATEX ) );
+                fmt.p_extra = malloc( fmt.i_extra );
+                memcpy( fmt.p_extra, &p_data[sizeof( WAVEFORMATEX )], fmt.i_extra );
             }
 
             p_stream->i_cat = AUDIO_ES;
-            p_stream->p_es = input_AddES( p_input,
-                         p_input->stream.p_selected_program,
-                         p_sp->i_stream_number, AUDIO_ES, NULL, 0 );
+            p_stream->p_es = es_out_Add( p_input->p_es_out, &fmt );
 
             msg_Dbg( p_input,
-                    "adding new audio stream(codec:0x%x,ID:%d)",
-                    i_codec,
-                    p_sp->i_stream_number );
-            wf_tag_to_fourcc( i_codec, &p_stream->p_es->i_fourcc, NULL );
-
-            if( p_sp->i_type_specific_data_length > 0 )
-            {
-                WAVEFORMATEX    *p_wf;
-                size_t          i_size;
-                uint8_t         *p_data;
-
-                i_size = p_sp->i_type_specific_data_length;
-
-                p_wf = malloc( i_size );
-                p_stream->p_es->p_waveformatex = (void*)p_wf;
-                p_data = p_sp->p_type_specific_data;
-
-                p_wf->wFormatTag        = GetWLE( p_data );
-                p_wf->nChannels         = GetWLE( p_data + 2 );
-                p_wf->nSamplesPerSec    = GetDWLE( p_data + 4 );
-                p_wf->nAvgBytesPerSec   = GetDWLE( p_data + 8 );
-                p_wf->nBlockAlign       = GetWLE( p_data + 12 );
-                p_wf->wBitsPerSample    = GetWLE( p_data + 14 );
-                p_wf->cbSize            = __MIN( GetWLE( p_data + 16 ), i_size - sizeof( WAVEFORMATEX ));
-                if( p_wf->cbSize > 0 )
-                {
-                    memcpy( &p_wf[1], p_data + sizeof( WAVEFORMATEX ), p_wf->cbSize );
-                }
-            }
+                    "added new audio stream(codec:0x%x,ID:%d)",
+                    GetWLE( p_data ), p_sp->i_stream_number );
         }
-        else
-        if( ASF_CmpGUID( &p_sp->i_stream_type, &asf_object_stream_type_video ) )
+        else if( ASF_CmpGUID( &p_sp->i_stream_type, &asf_object_stream_type_video ) &&
+                 p_sp->i_type_specific_data_length >= 11 + sizeof( BITMAPINFOHEADER ) )
         {
-            p_stream->i_cat = VIDEO_ES;
-            p_stream->p_es = input_AddES( p_input,
-                         p_input->stream.p_selected_program,
-                         p_sp->i_stream_number, VIDEO_ES, NULL, 0 );
+            es_format_t  fmt;
+            uint8_t      *p_data = &p_sp->p_type_specific_data[11];
 
-            msg_Dbg( p_input, "adding new video stream(ID:%d)",
-                     p_sp->i_stream_number );
-            if( p_sp->p_type_specific_data )
-            {
-                p_stream->p_es->i_fourcc =
-                    VLC_FOURCC( p_sp->p_type_specific_data[27],
-                                p_sp->p_type_specific_data[28],
-                                p_sp->p_type_specific_data[29],
-                                p_sp->p_type_specific_data[30] );
-            }
-            else
+            es_format_Init( &fmt, VIDEO_ES,
+                            VLC_FOURCC( p_data[16], p_data[17], p_data[18], p_data[19] ) );
+            fmt.video.i_width = GetDWLE( p_data + 4 );
+            fmt.video.i_height= GetDWLE( p_data + 8 );
+
+            if( p_sp->i_type_specific_data_length > 11 + sizeof( BITMAPINFOHEADER ) )
             {
-                p_stream->p_es->i_fourcc =
-                    VLC_FOURCC( 'u','n','d','f' );
-            }
-            if( p_sp->i_type_specific_data_length > 11 )
-            {
-                BITMAPINFOHEADER *p_bih;
-                size_t      i_size;
-                uint8_t     *p_data;
-
-                i_size = p_sp->i_type_specific_data_length - 11;
-
-                p_bih = malloc( i_size );
-                p_stream->p_es->p_bitmapinfoheader = (void*)p_bih;
-                p_data = p_sp->p_type_specific_data + 11;
-
-                p_bih->biSize       = GetDWLE( p_data );
-                p_bih->biWidth      = GetDWLE( p_data + 4 );
-                p_bih->biHeight     = GetDWLE( p_data + 8 );
-                p_bih->biPlanes     = GetDWLE( p_data + 12 );
-                p_bih->biBitCount   = GetDWLE( p_data + 14 );
-                p_bih->biCompression= GetDWLE( p_data + 16 );
-                p_bih->biSizeImage  = GetDWLE( p_data + 20 );
-                p_bih->biXPelsPerMeter = GetDWLE( p_data + 24 );
-                p_bih->biYPelsPerMeter = GetDWLE( p_data + 28 );
-                p_bih->biClrUsed       = GetDWLE( p_data + 32 );
-                p_bih->biClrImportant  = GetDWLE( p_data + 36 );
-
-                if( i_size > sizeof( BITMAPINFOHEADER ) )
-                {
-                    memcpy( &p_bih[1],
-                            p_data + sizeof( BITMAPINFOHEADER ),
-                            i_size - sizeof( BITMAPINFOHEADER ) );
-                }
+                fmt.i_extra = __MIN( GetDWLE( p_data ),
+                                     p_sp->i_type_specific_data_length - 11 - sizeof( BITMAPINFOHEADER ) );
+                fmt.p_extra = malloc( fmt.i_extra );
+                memcpy( fmt.p_extra, &p_data[sizeof( BITMAPINFOHEADER )], fmt.i_extra );
             }
 
+            p_stream->i_cat = VIDEO_ES;
+            p_stream->p_es = es_out_Add( p_input->p_es_out, &fmt );
+
+            msg_Dbg( p_input, "added new video stream(ID:%d)",
+                     p_sp->i_stream_number );
         }
         else
         {
@@ -305,16 +240,8 @@ static int Open( vlc_object_t * p_this )
             msg_Dbg( p_input, "ignoring unknown stream(ID:%d)",
                      p_sp->i_stream_number );
         }
-
-        vlc_mutex_lock( &p_input->stream.stream_lock );
-        if( p_stream->p_es )
-        {
-            input_SelectES( p_input, p_stream->p_es );
-        }
-        vlc_mutex_unlock( &p_input->stream.stream_lock );
     }
 
-
     p_sys->i_data_begin = p_sys->p_root->p_data->i_object_pos + 50;
     if( p_sys->p_root->p_data->i_object_size != 0 )
     { /* local file */
@@ -328,13 +255,13 @@ static int Open( vlc_object_t * p_this )
 
 
     /* go to first packet */
-    stream_Seek( p_sys->s, p_sys->i_data_begin );
+    stream_Seek( p_input->s, p_sys->i_data_begin );
 
     /* try to calculate movie time */
     if( p_sys->p_fp->i_data_packets_count > 0 )
     {
         int64_t i_count;
-        int64_t i_size = stream_Size( p_sys->s );
+        int64_t i_size = stream_Size( p_input->s );
 
         if( p_sys->i_data_end > 0 && i_size > p_sys->i_data_end )
         {
@@ -357,13 +284,10 @@ static int Open( vlc_object_t * p_this )
         }
     }
 
-    vlc_mutex_lock( &p_input->stream.stream_lock );
-    p_input->stream.p_selected_program->b_is_ok = 1;
-    vlc_mutex_unlock( &p_input->stream.stream_lock );
-
-
     /* We add all info about this stream */
-    p_cat = input_InfoCategory( p_input, "Asf" );
+    p_cat = input_InfoCategory( p_input, _("Asf") );
+    playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_input,
+                                     VLC_OBJECT_PLAYLIST,  FIND_PARENT);
     if( p_sys->i_length > 0 )
     {
         int64_t i_second = p_sys->i_length / (int64_t)1000000;
@@ -372,82 +296,95 @@ static int Open( vlc_object_t * p_this )
                        (int)(i_second / 36000),
                        (int)(( i_second / 60 ) % 60),
                        (int)(i_second % 60) );
+        if( p_playlist )
+        {
+            playlist_AddInfo( p_playlist, -1, _("Asf"), _("Length"),
+                               "%d:%d:%d",
+                               (int)(i_second / 36000),
+                               (int)(( i_second / 60 ) % 60),
+                               (int)(i_second % 60) );
+        }
     }
     input_AddInfo( p_cat, _("Number of streams"), "%d" , p_sys->i_streams );
+    if( p_playlist )
+    {
+        playlist_AddInfo( p_playlist, -1, _("Asf"),_("Number of streams"),"%d",
+                         p_sys->i_streams );
+    }
 
     if( ( p_cd = ASF_FindObject( p_sys->p_root->p_hdr,
                                  &asf_object_content_description_guid, 0 ) ) )
     {
         if( *p_cd->psz_title )
+        {
             input_AddInfo( p_cat, _("Title"), p_cd->psz_title );
+            playlist_AddInfo( p_playlist, -1, _("Asf"),_("Title"),
+                              p_cd->psz_title );
+            playlist_SetName( p_playlist, -1, p_cd->psz_title );
+        }
         if( p_cd->psz_author )
+        {
             input_AddInfo( p_cat, _("Author"), p_cd->psz_author );
+            playlist_AddInfo( p_playlist, -1, _("Asf"),_("Author"),
+                              p_cd->psz_author );
+            playlist_AddInfo( p_playlist, -1, _("General"),_("Author"),
+                              p_cd->psz_author );
+        }
         if( p_cd->psz_copyright )
+        {
             input_AddInfo( p_cat, _("Copyright"), p_cd->psz_copyright );
+            playlist_AddInfo( p_playlist, -1, _("Asf"),  _("Copyright"),
+                               p_cd->psz_copyright );
+        }
         if( *p_cd->psz_description )
+        {
             input_AddInfo( p_cat, _("Description"), p_cd->psz_description );
+            playlist_AddInfo( p_playlist, -1, _("Asf"),  _("Description"),
+                               p_cd->psz_description );
+        }
         if( *p_cd->psz_rating )
+        {
             input_AddInfo( p_cat, _("Rating"), p_cd->psz_rating );
+            playlist_AddInfo( p_playlist, -1, _("Asf"),  _("Rating"),
+                              p_cd->psz_rating );
+        }
     }
 
+    /* FIXME to port to new way */
     for( i_stream = 0, i = 0; i < 128; i++ )
     {
-        asf_stream_t *tk =  p_sys->stream[i];
         asf_object_codec_list_t *p_cl =
             ASF_FindObject( p_sys->p_root->p_hdr,
                             &asf_object_codec_list_guid, 0 );
-        char psz_cat[sizeof(_("Stream "))+10];
 
-        if( p_sys->stream[i] == NULL )
+        if( p_sys->stream[i] )
         {
-            continue;
-        }
-        sprintf( psz_cat, _("Stream %d"), i_stream );
-        p_cat = input_InfoCategory( p_input, psz_cat);
+            char *psz_cat = malloc( strlen(_("Stream")) + 10 );
+            sprintf( psz_cat, "%s %d", _("Stream"), i_stream );
+            p_cat = input_InfoCategory( p_input, psz_cat);
 
-        input_AddInfo( p_cat, _("Type"),
-                       ( tk->i_cat == AUDIO_ES ? _("Audio") : _("Video") ) );
-        input_AddInfo( p_cat, _("Codec"), "%.4s",
-                           (char*)&tk->p_es->i_fourcc );
-        if( p_cl && i_stream < p_cl->i_codec_entries_count )
-        {
-            input_AddInfo( p_cat, _("Codec name"),
-                           p_cl->codec[i_stream].psz_name );
-            input_AddInfo( p_cat, _("Codec description"),
-                           p_cl->codec[i_stream].psz_description );
-        }
-
-        if( tk->i_cat == AUDIO_ES && tk->p_es->p_waveformatex )
-        {
-            WAVEFORMATEX    *p_wf = tk->p_es->p_waveformatex;
-            input_AddInfo( p_cat, _("Channels"), "%d", p_wf->nChannels );
-            input_AddInfo( p_cat, _("Sample Rate"), "%d", p_wf->nSamplesPerSec );
-            input_AddInfo( p_cat, _("Avg. byterate"), "%d", p_wf->nAvgBytesPerSec );
-            input_AddInfo( p_cat, _("Bits Per Sample"), "%d", p_wf->wBitsPerSample );
-        }
-        else if( tk->i_cat == VIDEO_ES && tk->p_es->p_bitmapinfoheader )
-        {
-            BITMAPINFOHEADER *p_bih = tk->p_es->p_bitmapinfoheader;
-
-            input_AddInfo( p_cat, _("Resolution"), "%dx%d",
-                           p_bih->biWidth, p_bih->biHeight );
-            input_AddInfo( p_cat, _("Planes"), "%d", p_bih->biPlanes );
-            input_AddInfo( p_cat, _("Bits Per Pixel"), "%d", p_bih->biBitCount );
-            input_AddInfo( p_cat, _("Image Size"), "%d", p_bih->biSizeImage );
-            input_AddInfo( p_cat, _("X pixels per meter"), "%d",
-                           p_bih->biXPelsPerMeter );
-            input_AddInfo( p_cat, _("Y pixels per meter"), "%d",
-                           p_bih->biYPelsPerMeter );
+            if( p_cl && i_stream < p_cl->i_codec_entries_count )
+            {
+                input_AddInfo( p_cat, _("Codec name"),
+                               p_cl->codec[i_stream].psz_name );
+                playlist_AddInfo( p_playlist, -1, psz_cat, _("Codec name"),
+                                  p_cl->codec[i_stream].psz_name );
+                input_AddInfo( p_cat, _("Codec description"),
+                               p_cl->codec[i_stream].psz_description );
+                playlist_AddInfo( p_playlist, -1, psz_cat,
+                                _("Codec description"),
+                                 p_cl->codec[i_stream].psz_description );
+            }
+            free( psz_cat );
+            i_stream++;
         }
-
-        i_stream++;
     }
 
+    if( p_playlist ) vlc_object_release( p_playlist );
     return VLC_SUCCESS;
 
 error:
-    ASF_FreeObjectRoot( p_sys->s, p_sys->p_root );
-    stream_Release( p_sys->s );
+    ASF_FreeObjectRoot( p_input->s, p_sys->p_root );
     free( p_sys );
     return VLC_EGENERIC;
 }
@@ -461,23 +398,6 @@ static int Demux( input_thread_t *p_input )
     demux_sys_t *p_sys = p_input->p_demux_data;
     vlc_bool_t b_play_audio;
     int i;
-    vlc_bool_t b_stream;
-
-    b_stream = VLC_FALSE;
-    for( i = 0; i < 128; i++ )
-    {
-        if( p_sys->stream[i] &&
-            p_sys->stream[i]->p_es &&
-            p_sys->stream[i]->p_es->p_decoder_fifo )
-        {
-            b_stream = VLC_TRUE;
-        }
-    }
-    if( !b_stream )
-    {
-        msg_Warn( p_input, "no stream selected, exiting..." );
-        return( 0 );
-    }
 
     /* catch seek from user */
     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
@@ -486,7 +406,7 @@ static int Demux( input_thread_t *p_input )
 
         msleep( p_input->i_pts_delay );
 
-        i_offset = stream_Tell( p_sys->s ) - p_sys->i_data_begin;
+        i_offset = stream_Tell( p_input->s ) - p_sys->i_data_begin;
         if( i_offset  < 0 )
         {
             i_offset = 0;
@@ -496,7 +416,7 @@ static int Demux( input_thread_t *p_input )
             i_offset -= i_offset % p_sys->p_fp->i_min_data_packet_size;
         }
 
-        if( stream_Seek( p_sys->s, i_offset + p_sys->i_data_begin ) )
+        if( stream_Seek( p_input->s, i_offset + p_sys->i_data_begin ) )
         {
             msg_Warn( p_input, "cannot resynch after seek (EOF?)" );
             return -1;
@@ -566,23 +486,22 @@ static void Close( vlc_object_t * p_this )
     demux_sys_t    *p_sys = p_input->p_demux_data;
     int i_stream;
 
-    msg_Dbg( p_input, "Freeing all memory" );
+    msg_Dbg( p_input, "freeing all memory" );
 
-    ASF_FreeObjectRoot( p_sys->s, p_sys->p_root );
+    ASF_FreeObjectRoot( p_input->s, p_sys->p_root );
     for( i_stream = 0; i_stream < 128; i_stream++ )
     {
-#define p_stream p_sys->stream[i_stream]
+        asf_stream_t *p_stream = p_sys->stream[i_stream];
+
         if( p_stream )
         {
-            if( p_stream->p_pes )
+            if( p_stream->p_frame )
             {
-                input_DeletePES( p_input->p_method_data, p_stream->p_pes );
+                block_ChainRelease( p_stream->p_frame );
             }
             free( p_stream );
         }
-#undef p_stream
     }
-    stream_Release( p_sys->s );
     free( p_sys );
 }
 
@@ -598,8 +517,9 @@ static mtime_t GetMoviePTS( demux_sys_t *p_sys )
     i_time = -1;
     for( i_stream = 0; i_stream < 128 ; i_stream++ )
     {
-#define p_stream p_sys->stream[i_stream]
-        if( p_stream && p_stream->p_es && p_stream->p_es->p_decoder_fifo && p_stream->i_time > 0)
+        asf_stream_t *p_stream = p_sys->stream[i_stream];
+
+        if( p_stream && p_stream->p_es && p_stream->i_time > 0)
         {
             if( i_time < 0 )
             {
@@ -610,7 +530,6 @@ static mtime_t GetMoviePTS( demux_sys_t *p_sys )
                 i_time = __MIN( i_time, p_stream->i_time );
             }
         }
-#undef p_stream
     }
 
     return( i_time );
@@ -649,7 +568,7 @@ static int DemuxPacket( input_thread_t *p_input, vlc_bool_t b_play_audio )
     int         i_payload_length_type;
 
 
-    if( stream_Peek( p_sys->s, &p_peek, i_data_packet_min ) < i_data_packet_min )
+    if( stream_Peek( p_input->s, &p_peek,i_data_packet_min)<i_data_packet_min )
     {
         // EOF ?
         msg_Warn( p_input, "cannot peek while getting new packet, EOF ?" );
@@ -814,7 +733,7 @@ static int DemuxPacket( input_thread_t *p_input, vlc_bool_t b_play_audio )
             continue;   // over payload
         }
 
-        if( !p_stream->p_es || !p_stream->p_es->p_decoder_fifo )
+        if( !p_stream->p_es )
         {
             i_skip += i_payload_data_length;
             continue;
@@ -826,8 +745,9 @@ static int DemuxPacket( input_thread_t *p_input, vlc_bool_t b_play_audio )
                     i_packet_size_left > 0;
              i_payload_data_pos += i_sub_payload_data_length )
         {
-            data_packet_t  *p_data;
+            block_t *p_frag;
             int i_read;
+
             // read sub payload length
             if( i_replicated_data_length == 1 )
             {
@@ -840,72 +760,53 @@ static int DemuxPacket( input_thread_t *p_input, vlc_bool_t b_play_audio )
             }
 
             /* FIXME I don't use i_media_object_number, sould I ? */
-            if( p_stream->p_pes && i_media_object_offset == 0 )
+            if( p_stream->p_frame && i_media_object_offset == 0 )
             {
                 /* send complete packet to decoder */
-                if( p_stream->p_pes->i_pes_size > 0 )
-                {
-                    if( p_stream->p_es->p_decoder_fifo &&
-                        ( b_play_audio || p_stream->i_cat != AUDIO_ES ) )
-                    {
-                        p_stream->p_pes->i_rate =
-                            p_input->stream.control.i_rate;
-                        input_DecodePES( p_stream->p_es->p_decoder_fifo,
-                                         p_stream->p_pes );
-                    }
-                    else
-                    {
-                        input_DeletePES( p_input->p_method_data,
-                                         p_stream->p_pes );
-                    }
-                    p_stream->p_pes = NULL;
-                }
-            }
+                block_t *p_gather = block_ChainGather( p_stream->p_frame );
 
-            if( !p_stream->p_pes )  // add a new PES
-            {
-                p_stream->i_time =
-                    ( (mtime_t)i_pts + i_payload * (mtime_t)i_pts_delta );
+                es_out_Send( p_input->p_es_out, p_stream->p_es, p_gather );
 
-                p_stream->p_pes = input_NewPES( p_input->p_method_data );
-                p_stream->p_pes->i_dts =
-                    p_stream->p_pes->i_pts =
-                        input_ClockGetTS( p_input,
-                                          p_input->stream.p_selected_program,
-                                          p_stream->i_time * 9 /100 );
-
-                //msg_Err( p_input, "stream[0x%2x] pts=%lld", i_stream_number, p_stream->p_pes->i_pts );
-                p_stream->p_pes->p_next = NULL;
-                p_stream->p_pes->i_nb_data = 0;
-                p_stream->p_pes->i_pes_size = 0;
+                p_stream->p_frame = NULL;
             }
 
             i_read = i_sub_payload_data_length + i_skip;
-            if((p_data = stream_DataPacket( p_sys->s,i_read,VLC_TRUE)) == NULL)
+            if( ( p_frag = stream_Block( p_input->s, i_read ) ) == NULL )
             {
                 msg_Warn( p_input, "cannot read data" );
                 return( 0 );
             }
-            p_data->p_payload_start += i_skip;
             i_packet_size_left -= i_read;
 
+            p_frag->p_buffer += i_skip;
+            p_frag->i_buffer -= i_skip;
 
-            if( !p_stream->p_pes->p_first )
-            {
-                p_stream->p_pes->p_first = p_stream->p_pes->p_last = p_data;
-            }
-            else
+            if( p_stream->p_frame == NULL )
             {
-                p_stream->p_pes->p_last->p_next = p_data;
-                p_stream->p_pes->p_last = p_data;
+                p_stream->i_time =
+                    ( (mtime_t)i_pts + i_payload * (mtime_t)i_pts_delta );
+
+                p_frag->i_pts =
+                    input_ClockGetTS( p_input,
+                                      p_input->stream.p_selected_program,
+                                      p_stream->i_time * 9 /100 );
+
+                if( p_stream->i_cat != VIDEO_ES )
+                    p_frag->i_dts = p_frag->i_pts;
+                else
+                {
+                    p_frag->i_dts = p_frag->i_pts;
+                    p_frag->i_pts = 0;
+                }
             }
-            p_stream->p_pes->i_pes_size += i_sub_payload_data_length;
-            p_stream->p_pes->i_nb_data++;
+
+            block_ChainAppend( &p_stream->p_frame, p_frag );
 
             i_skip = 0;
             if( i_packet_size_left > 0 )
             {
-                if( stream_Peek( p_sys->s, &p_peek, i_packet_size_left ) < i_packet_size_left )
+                if( stream_Peek( p_input->s, &p_peek, i_packet_size_left )
+                                                         < i_packet_size_left )
                 {
                     // EOF ?
                     msg_Warn( p_input, "cannot peek, EOF ?" );
@@ -917,7 +818,8 @@ static int DemuxPacket( input_thread_t *p_input, vlc_bool_t b_play_audio )
 
     if( i_packet_size_left > 0 )
     {
-        if( stream_Read( p_sys->s, NULL, i_packet_size_left ) < i_packet_size_left )
+        if( stream_Read( p_input->s, NULL, i_packet_size_left )
+                                                         < i_packet_size_left )
         {
             msg_Warn( p_input, "cannot skip data, EOF ?" );
             return( 0 );
@@ -933,7 +835,7 @@ loop_error_recovery:
         msg_Err( p_input, "unsupported packet header, fatal error" );
         return( -1 );
     }
-    stream_Read( p_sys->s, NULL, i_data_packet_min );
+    stream_Read( p_input->s, NULL, i_data_packet_min );
 
     return( 1 );
 }