57aaab1e7744dd24f15490f4674653f18e5b4f5e
[vlc.git] / modules / demux / asf / asf.c
1 /*****************************************************************************
2  * asf.c : ASFv01 file input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2002-2003 VideoLAN
5  * $Id: asf.c,v 1.34 2003/08/18 19:18:47 fenrir Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28
29 #include <vlc/vlc.h>
30 #include <vlc/input.h>
31 #include "ninput.h"
32
33 #include "codecs.h"                        /* BITMAPINFOHEADER, WAVEFORMATEX */
34 #include "libasf.h"
35
36 /*****************************************************************************
37  * Module descriptor
38  *****************************************************************************/
39 static int  Open  ( vlc_object_t * );
40 static void Close ( vlc_object_t * );
41
42 vlc_module_begin();
43     set_description( _("ASF v1.0 demuxer") );
44     set_capability( "demux", 200 );
45     set_callbacks( Open, Close );
46     add_shortcut( "asf" );
47 vlc_module_end();
48
49
50 /*****************************************************************************
51  * Local prototypes
52  *****************************************************************************/
53 static int  Demux   ( input_thread_t * );
54
55 typedef struct asf_stream_s
56 {
57     int i_cat;
58     es_descriptor_t *p_es;
59     asf_object_stream_properties_t *p_sp;
60
61     mtime_t i_time;
62
63     pes_packet_t    *p_pes;     /* used to keep uncomplete frames */
64
65 } asf_stream_t;
66
67 struct demux_sys_t
68 {
69     mtime_t             i_time;     /* µs */
70     mtime_t             i_length;   /* length of file file */
71
72     asf_object_root_t            *p_root;
73     asf_object_file_properties_t *p_fp;
74
75     unsigned int        i_streams;
76     asf_stream_t        *stream[128];
77
78     int64_t             i_data_begin;
79     int64_t             i_data_end;
80
81     stream_t            *s;
82 };
83
84 static mtime_t  GetMoviePTS( demux_sys_t * );
85 static int      DemuxPacket( input_thread_t *, vlc_bool_t b_play_audio );
86
87 /*****************************************************************************
88  * Open: check file and initializes ASF structures
89  *****************************************************************************/
90 static int Open( vlc_object_t * p_this )
91 {
92     input_thread_t  *p_input = (input_thread_t *)p_this;
93     uint8_t         *p_peek;
94
95     guid_t          guid;
96
97     demux_sys_t     *p_sys;
98     unsigned int    i_stream;
99     unsigned int    i;
100     asf_object_content_description_t *p_cd;
101
102     vlc_bool_t      b_seekable;
103
104     input_info_category_t *p_cat;
105
106     /* a little test to see if it could be a asf stream */
107     if( input_Peek( p_input, &p_peek, 16 ) < 16 )
108     {
109         msg_Warn( p_input, "ASF plugin discarded (cannot peek)" );
110         return VLC_EGENERIC;
111     }
112     ASF_GetGUID( &guid, p_peek );
113     if( !ASF_CmpGUID( &guid, &asf_object_header_guid ) )
114     {
115         msg_Warn( p_input, "ASF plugin discarded (not a valid file)" );
116         return VLC_EGENERIC;
117     }
118
119     /* Set p_input field */
120     p_input->pf_demux = Demux;
121     p_input->p_demux_data = p_sys = malloc( sizeof( demux_sys_t ) );
122     memset( p_sys, 0, sizeof( demux_sys_t ) );
123     p_sys->i_time = -1;
124     p_sys->i_length = 0;
125
126     /* Create stream facilities */
127     if( ( p_sys->s = stream_OpenInput( p_input ) ) == NULL )
128     {
129         msg_Err( p_input, "cannot create stream" );
130         free( p_sys );
131         return VLC_EGENERIC;
132     }
133
134     /* Now load all object ( except raw data ) */
135     stream_Control( p_sys->s, STREAM_CAN_FASTSEEK, &b_seekable );
136     if( (p_sys->p_root = ASF_ReadObjectRoot( p_sys->s, b_seekable )) == NULL )
137     {
138         msg_Warn( p_input, "ASF plugin discarded (not a valid file)" );
139         stream_Release( p_sys->s );
140         free( p_sys );
141         return VLC_EGENERIC;
142     }
143     p_sys->p_fp = p_sys->p_root->p_fp;
144
145     if( p_sys->p_fp->i_min_data_packet_size != p_sys->p_fp->i_max_data_packet_size )
146     {
147         msg_Warn( p_input,
148                   "ASF plugin discarded (invalid file_properties object)" );
149         goto error;
150     }
151
152     p_sys->i_streams = ASF_CountObject( p_sys->p_root->p_hdr,
153                                           &asf_object_stream_properties_guid );
154     if( !p_sys->i_streams )
155     {
156         msg_Warn( p_input, "ASF plugin discarded (cannot find any stream!)" );
157         goto error;
158     }
159
160     msg_Dbg( p_input, "found %d streams", p_sys->i_streams );
161
162     /*  create one program */
163     vlc_mutex_lock( &p_input->stream.stream_lock );
164     if( input_InitStream( p_input, 0 ) == -1)
165     {
166         vlc_mutex_unlock( &p_input->stream.stream_lock );
167         msg_Err( p_input, "cannot init stream" );
168         goto error;
169     }
170     if( input_AddProgram( p_input, 0, 0) == NULL )
171     {
172         vlc_mutex_unlock( &p_input->stream.stream_lock );
173         msg_Err( p_input, "cannot add program" );
174         goto error;
175     }
176     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
177     p_input->stream.i_mux_rate = 0 ; /* updated later */
178     vlc_mutex_unlock( &p_input->stream.stream_lock );
179
180     for( i_stream = 0; i_stream < p_sys->i_streams; i_stream ++ )
181     {
182         asf_stream_t    *p_stream;
183         asf_object_stream_properties_t *p_sp;
184
185         p_sp = ASF_FindObject( p_sys->p_root->p_hdr,
186                                &asf_object_stream_properties_guid,
187                                i_stream );
188
189         p_stream =
190             p_sys->stream[p_sp->i_stream_number] =
191                 malloc( sizeof( asf_stream_t ) );
192         memset( p_stream, 0, sizeof( asf_stream_t ) );
193
194         p_stream->i_time = -1;
195         p_stream->p_sp = p_sp;
196         p_stream->p_es = NULL;
197
198         if( ASF_CmpGUID( &p_sp->i_stream_type, &asf_object_stream_type_audio ) )
199         {
200             int i_codec;
201             if( p_sp->p_type_specific_data )
202             {
203                 i_codec = GetWLE( p_sp->p_type_specific_data );
204             }
205             else
206             {
207                 i_codec = -1;
208             }
209
210             p_stream->i_cat = AUDIO_ES;
211             p_stream->p_es = input_AddES( p_input,
212                          p_input->stream.p_selected_program,
213                          p_sp->i_stream_number, AUDIO_ES, NULL, 0 );
214
215             msg_Dbg( p_input,
216                     "adding new audio stream(codec:0x%x,ID:%d)",
217                     i_codec,
218                     p_sp->i_stream_number );
219             wf_tag_to_fourcc( i_codec, &p_stream->p_es->i_fourcc, NULL );
220
221             if( p_sp->i_type_specific_data_length > 0 )
222             {
223                 WAVEFORMATEX    *p_wf;
224                 size_t          i_size;
225                 uint8_t         *p_data;
226
227                 i_size = p_sp->i_type_specific_data_length;
228
229                 p_wf = malloc( i_size );
230                 p_stream->p_es->p_waveformatex = (void*)p_wf;
231                 p_data = p_sp->p_type_specific_data;
232
233                 p_wf->wFormatTag        = GetWLE( p_data );
234                 p_wf->nChannels         = GetWLE( p_data + 2 );
235                 p_wf->nSamplesPerSec    = GetDWLE( p_data + 4 );
236                 p_wf->nAvgBytesPerSec   = GetDWLE( p_data + 8 );
237                 p_wf->nBlockAlign       = GetWLE( p_data + 12 );
238                 p_wf->wBitsPerSample    = GetWLE( p_data + 14 );
239                 p_wf->cbSize            = __MIN( GetWLE( p_data + 16 ), i_size - sizeof( WAVEFORMATEX ));
240                 if( p_wf->cbSize > 0 )
241                 {
242                     memcpy( &p_wf[1], p_data + sizeof( WAVEFORMATEX ), p_wf->cbSize );
243                 }
244             }
245         }
246         else
247         if( ASF_CmpGUID( &p_sp->i_stream_type, &asf_object_stream_type_video ) )
248         {
249             p_stream->i_cat = VIDEO_ES;
250             p_stream->p_es = input_AddES( p_input,
251                          p_input->stream.p_selected_program,
252                          p_sp->i_stream_number, VIDEO_ES, NULL, 0 );
253
254             msg_Dbg( p_input, "adding new video stream(ID:%d)",
255                      p_sp->i_stream_number );
256             if( p_sp->p_type_specific_data )
257             {
258                 p_stream->p_es->i_fourcc =
259                     VLC_FOURCC( p_sp->p_type_specific_data[27],
260                                 p_sp->p_type_specific_data[28],
261                                 p_sp->p_type_specific_data[29],
262                                 p_sp->p_type_specific_data[30] );
263             }
264             else
265             {
266                 p_stream->p_es->i_fourcc =
267                     VLC_FOURCC( 'u','n','d','f' );
268             }
269             if( p_sp->i_type_specific_data_length > 11 )
270             {
271                 BITMAPINFOHEADER *p_bih;
272                 size_t      i_size;
273                 uint8_t     *p_data;
274
275                 i_size = p_sp->i_type_specific_data_length - 11;
276
277                 p_bih = malloc( i_size );
278                 p_stream->p_es->p_bitmapinfoheader = (void*)p_bih;
279                 p_data = p_sp->p_type_specific_data + 11;
280
281                 p_bih->biSize       = GetDWLE( p_data );
282                 p_bih->biWidth      = GetDWLE( p_data + 4 );
283                 p_bih->biHeight     = GetDWLE( p_data + 8 );
284                 p_bih->biPlanes     = GetDWLE( p_data + 12 );
285                 p_bih->biBitCount   = GetDWLE( p_data + 14 );
286                 p_bih->biCompression= GetDWLE( p_data + 16 );
287                 p_bih->biSizeImage  = GetDWLE( p_data + 20 );
288                 p_bih->biXPelsPerMeter = GetDWLE( p_data + 24 );
289                 p_bih->biYPelsPerMeter = GetDWLE( p_data + 28 );
290                 p_bih->biClrUsed       = GetDWLE( p_data + 32 );
291                 p_bih->biClrImportant  = GetDWLE( p_data + 36 );
292
293                 if( i_size > sizeof( BITMAPINFOHEADER ) )
294                 {
295                     memcpy( &p_bih[1],
296                             p_data + sizeof( BITMAPINFOHEADER ),
297                             i_size - sizeof( BITMAPINFOHEADER ) );
298                 }
299             }
300
301         }
302         else
303         {
304             p_stream->i_cat = UNKNOWN_ES;
305             msg_Dbg( p_input, "ignoring unknown stream(ID:%d)",
306                      p_sp->i_stream_number );
307         }
308
309         vlc_mutex_lock( &p_input->stream.stream_lock );
310         if( p_stream->p_es )
311         {
312             input_SelectES( p_input, p_stream->p_es );
313         }
314         vlc_mutex_unlock( &p_input->stream.stream_lock );
315     }
316
317
318     p_sys->i_data_begin = p_sys->p_root->p_data->i_object_pos + 50;
319     if( p_sys->p_root->p_data->i_object_size != 0 )
320     { // local file
321         p_sys->i_data_end = p_sys->p_root->p_data->i_object_pos +
322                                     p_sys->p_root->p_data->i_object_size;
323     }
324     else
325     { // live/broacast
326         p_sys->i_data_end = -1;
327     }
328
329
330     // go to first packet
331     stream_Control( p_sys->s, STREAM_SET_POSITION, (int64_t)p_sys->i_data_begin );
332
333     /* try to calculate movie time */
334     if( p_sys->p_fp->i_data_packets_count > 0 )
335     {
336         int64_t i_count;
337         int64_t i_size;
338
339         stream_Control( p_sys->s, STREAM_GET_SIZE, &i_size );
340         if( p_sys->i_data_end > 0 && i_size > p_sys->i_data_end )
341         {
342             i_size = p_sys->i_data_end;
343         }
344
345         /* real number of packets */
346         i_count = ( i_size - p_sys->i_data_begin ) /
347                   p_sys->p_fp->i_min_data_packet_size;
348
349         /* calculate the time duration in micro-s */
350         p_sys->i_length = (mtime_t)p_sys->p_fp->i_play_duration / 10 *
351                    (mtime_t)i_count /
352                    (mtime_t)p_sys->p_fp->i_data_packets_count;
353
354         if( p_sys->i_length > 0 )
355         {
356             p_input->stream.i_mux_rate =
357                 i_size / 50 * (int64_t)1000000 / p_sys->i_length;
358         }
359     }
360
361     vlc_mutex_lock( &p_input->stream.stream_lock );
362     p_input->stream.p_selected_program->b_is_ok = 1;
363     vlc_mutex_unlock( &p_input->stream.stream_lock );
364
365
366     /* We add all info about this stream */
367     p_cat = input_InfoCategory( p_input, "Asf" );
368     if( p_sys->i_length > 0 )
369     {
370         int64_t i_second = p_sys->i_length / (int64_t)1000000;
371
372         input_AddInfo( p_cat, _("Length"), "%d:%d:%d",
373                        (int)(i_second / 36000),
374                        (int)(( i_second / 60 ) % 60),
375                        (int)(i_second % 60) );
376     }
377     input_AddInfo( p_cat, _("Number of streams"), "%d" , p_sys->i_streams );
378
379     if( ( p_cd = ASF_FindObject( p_sys->p_root->p_hdr,
380                                  &asf_object_content_description_guid, 0 ) ) )
381     {
382         if( *p_cd->psz_title )
383             input_AddInfo( p_cat, _("Title"), p_cd->psz_title );
384         if( p_cd->psz_author )
385             input_AddInfo( p_cat, _("Author"), p_cd->psz_author );
386         if( p_cd->psz_copyright )
387             input_AddInfo( p_cat, _("Copyright"), p_cd->psz_copyright );
388         if( *p_cd->psz_description )
389             input_AddInfo( p_cat, _("Description"), p_cd->psz_description );
390         if( *p_cd->psz_rating )
391             input_AddInfo( p_cat, _("Rating"), p_cd->psz_rating );
392     }
393
394     for( i_stream = 0, i = 0; i < 128; i++ )
395     {
396         asf_stream_t *tk =  p_sys->stream[i];
397         asf_object_codec_list_t *p_cl =
398             ASF_FindObject( p_sys->p_root->p_hdr,
399                             &asf_object_codec_list_guid, 0 );
400         char psz_cat[sizeof(_("Stream "))+10];
401
402         if( p_sys->stream[i] == NULL )
403         {
404             continue;
405         }
406         sprintf( psz_cat, _("Stream %d"), i_stream );
407         p_cat = input_InfoCategory( p_input, psz_cat);
408
409         input_AddInfo( p_cat, _("Type"),
410                        ( tk->i_cat == AUDIO_ES ? _("Audio") : _("Video") ) );
411         input_AddInfo( p_cat, _("Codec"), "%.4s",
412                            (char*)&tk->p_es->i_fourcc );
413         if( p_cl && i_stream < p_cl->i_codec_entries_count )
414         {
415             input_AddInfo( p_cat, _("Codec name"),
416                            p_cl->codec[i_stream].psz_name );
417             input_AddInfo( p_cat, _("Codec description"),
418                            p_cl->codec[i_stream].psz_description );
419         }
420
421         if( tk->i_cat == AUDIO_ES && tk->p_es->p_waveformatex )
422         {
423             WAVEFORMATEX    *p_wf = tk->p_es->p_waveformatex;
424             input_AddInfo( p_cat, _("Channels"), "%d", p_wf->nChannels );
425             input_AddInfo( p_cat, _("Sample Rate"), "%d", p_wf->nSamplesPerSec );
426             input_AddInfo( p_cat, _("Avg. byterate"), "%d", p_wf->nAvgBytesPerSec );
427             input_AddInfo( p_cat, _("Bits Per Sample"), "%d", p_wf->wBitsPerSample );
428         }
429         else if( tk->i_cat == VIDEO_ES && tk->p_es->p_bitmapinfoheader )
430         {
431             BITMAPINFOHEADER *p_bih = tk->p_es->p_bitmapinfoheader;
432
433             input_AddInfo( p_cat, _("Resolution"), "%dx%d",
434                            p_bih->biWidth, p_bih->biHeight );
435             input_AddInfo( p_cat, _("Planes"), "%d", p_bih->biPlanes );
436             input_AddInfo( p_cat, _("Bits Per Pixel"), "%d", p_bih->biBitCount );
437             input_AddInfo( p_cat, _("Image Size"), "%d", p_bih->biSizeImage );
438             input_AddInfo( p_cat, _("X pixels per meter"), "%d",
439                            p_bih->biXPelsPerMeter );
440             input_AddInfo( p_cat, _("Y pixels per meter"), "%d",
441                            p_bih->biYPelsPerMeter );
442         }
443
444         i_stream++;
445     }
446
447     return VLC_SUCCESS;
448
449 error:
450     ASF_FreeObjectRoot( p_sys->s, p_sys->p_root );
451     stream_Release( p_sys->s );
452     free( p_sys );
453     return VLC_EGENERIC;
454 }
455
456
457 /*****************************************************************************
458  * Demux: read packet and send them to decoders
459  *****************************************************************************/
460 static int Demux( input_thread_t *p_input )
461 {
462     demux_sys_t *p_sys = p_input->p_demux_data;
463     vlc_bool_t b_play_audio;
464     int i;
465     vlc_bool_t b_stream;
466
467     b_stream = VLC_FALSE;
468     for( i = 0; i < 128; i++ )
469     {
470         if( p_sys->stream[i] &&
471             p_sys->stream[i]->p_es &&
472             p_sys->stream[i]->p_es->p_decoder_fifo )
473         {
474             b_stream = VLC_TRUE;
475         }
476     }
477     if( !b_stream )
478     {
479         msg_Warn( p_input, "no stream selected, exiting..." );
480         return( 0 );
481     }
482
483     /* catch seek from user */
484     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
485     {
486         int64_t i_offset;
487
488         msleep( p_input->i_pts_delay );
489
490         stream_Control( p_sys->s, STREAM_GET_POSITION, &i_offset );
491         i_offset -= p_sys->i_data_begin;
492         if( i_offset  < 0 )
493         {
494             i_offset = 0;
495         }
496         if( i_offset % p_sys->p_fp->i_min_data_packet_size > 0 )
497         {
498             i_offset -= i_offset % p_sys->p_fp->i_min_data_packet_size;
499         }
500         i_offset += p_sys->i_data_begin;
501
502         if( stream_Control( p_sys->s, STREAM_SET_POSITION, i_offset ) )
503         {
504             msg_Warn( p_input, "cannot resynch after seek (EOF?)" );
505             return -1;
506         }
507
508         p_sys->i_time = -1;
509         for( i = 0; i < 128 ; i++ )
510         {
511 #define p_stream p_sys->stream[i]
512             if( p_stream )
513             {
514                 p_stream->i_time = -1;
515             }
516 #undef p_stream
517         }
518     }
519
520     /* Check if we need to send the audio data to decoder */
521     b_play_audio = !p_input->stream.control.b_mute;
522
523     for( ;; )
524     {
525         mtime_t i_length;
526         mtime_t i_time_begin = GetMoviePTS( p_sys );
527         int i_result;
528
529         if( p_input->b_die )
530         {
531             break;
532         }
533
534         if( ( i_result = DemuxPacket( p_input, b_play_audio ) ) <= 0 )
535         {
536             return i_result;
537         }
538         if( i_time_begin == -1 )
539         {
540             i_time_begin = GetMoviePTS( p_sys );
541         }
542         else
543         {
544             i_length = GetMoviePTS( p_sys ) - i_time_begin;
545             if( i_length < 0 || i_length >= 40 * 1000 )
546             {
547                 break;
548             }
549         }
550     }
551
552     p_sys->i_time = GetMoviePTS( p_sys );
553     if( p_sys->i_time >= 0 )
554     {
555         input_ClockManageRef( p_input,
556                               p_input->stream.p_selected_program,
557                               p_sys->i_time * 9 / 100 );
558     }
559
560     return( 1 );
561 }
562
563 /*****************************************************************************
564  * Close: frees unused data
565  *****************************************************************************/
566 static void Close( vlc_object_t * p_this )
567 {
568     input_thread_t *p_input = (input_thread_t *)p_this;
569     demux_sys_t    *p_sys = p_input->p_demux_data;
570     int i_stream;
571
572     msg_Dbg( p_input, "Freeing all memory" );
573
574     ASF_FreeObjectRoot( p_sys->s, p_sys->p_root );
575     for( i_stream = 0; i_stream < 128; i_stream++ )
576     {
577 #define p_stream p_sys->stream[i_stream]
578         if( p_stream )
579         {
580             if( p_stream->p_pes )
581             {
582                 input_DeletePES( p_input->p_method_data, p_stream->p_pes );
583             }
584             free( p_stream );
585         }
586 #undef p_stream
587     }
588     stream_Release( p_sys->s );
589     free( p_sys );
590 }
591
592
593 /*****************************************************************************
594  *
595  *****************************************************************************/
596 static mtime_t GetMoviePTS( demux_sys_t *p_sys )
597 {
598     mtime_t i_time;
599     int     i_stream;
600
601     i_time = -1;
602     for( i_stream = 0; i_stream < 128 ; i_stream++ )
603     {
604 #define p_stream p_sys->stream[i_stream]
605         if( p_stream && p_stream->p_es && p_stream->p_es->p_decoder_fifo && p_stream->i_time > 0)
606         {
607             if( i_time < 0 )
608             {
609                 i_time = p_stream->i_time;
610             }
611             else
612             {
613                 i_time = __MIN( i_time, p_stream->i_time );
614             }
615         }
616 #undef p_stream
617     }
618
619     return( i_time );
620 }
621
622 #define GETVALUE2b( bits, var, def ) \
623     switch( (bits)&0x03 ) \
624     { \
625         case 1: var = p_peek[i_skip]; i_skip++; break; \
626         case 2: var = GetWLE( p_peek + i_skip );  i_skip+= 2; break; \
627         case 3: var = GetDWLE( p_peek + i_skip ); i_skip+= 4; break; \
628         case 0: \
629         default: var = def; break;\
630     }
631
632 static int DemuxPacket( input_thread_t *p_input, vlc_bool_t b_play_audio )
633 {
634     demux_sys_t *p_sys = p_input->p_demux_data;
635     int     i_data_packet_min = p_sys->p_fp->i_min_data_packet_size;
636     uint8_t *p_peek;
637     int     i_skip;
638
639     int     i_packet_size_left;
640     int     i_packet_flags;
641     int     i_packet_property;
642
643     int     b_packet_multiple_payload;
644     int     i_packet_length;
645     int     i_packet_sequence;
646     int     i_packet_padding_length;
647
648     uint32_t    i_packet_send_time;
649     uint16_t    i_packet_duration;
650     int         i_payload;
651     int         i_payload_count;
652     int         i_payload_length_type;
653
654
655     if( stream_Peek( p_sys->s, &p_peek, i_data_packet_min ) < i_data_packet_min )
656     {
657         // EOF ?
658         msg_Warn( p_input, "cannot peek while getting new packet, EOF ?" );
659         return( 0 );
660     }
661     i_skip = 0;
662
663     /* *** parse error correction if present *** */
664     if( p_peek[0]&0x80 )
665     {
666         unsigned int i_error_correction_length_type;
667         unsigned int i_error_correction_data_length;
668         unsigned int i_opaque_data_present;
669
670         i_error_correction_data_length = p_peek[0] & 0x0f;  // 4bits
671         i_opaque_data_present = ( p_peek[0] >> 4 )& 0x01;    // 1bit
672         i_error_correction_length_type = ( p_peek[0] >> 5 ) & 0x03; // 2bits
673         i_skip += 1; // skip error correction flags
674
675         if( i_error_correction_length_type != 0x00 ||
676             i_opaque_data_present != 0 ||
677             i_error_correction_data_length != 0x02 )
678         {
679             goto loop_error_recovery;
680         }
681
682         i_skip += i_error_correction_data_length;
683     }
684     else
685     {
686         msg_Warn( p_input, "p_peek[0]&0x80 != 0x80" );
687     }
688
689     /* sanity check */
690     if( i_skip + 2 >= i_data_packet_min )
691     {
692         goto loop_error_recovery;
693     }
694
695     i_packet_flags = p_peek[i_skip]; i_skip++;
696     i_packet_property = p_peek[i_skip]; i_skip++;
697
698     b_packet_multiple_payload = i_packet_flags&0x01;
699
700     /* read some value */
701     GETVALUE2b( i_packet_flags >> 5, i_packet_length, i_data_packet_min );
702     GETVALUE2b( i_packet_flags >> 1, i_packet_sequence, 0 );
703     GETVALUE2b( i_packet_flags >> 3, i_packet_padding_length, 0 );
704
705     i_packet_send_time = GetDWLE( p_peek + i_skip ); i_skip += 4;
706     i_packet_duration  = GetWLE( p_peek + i_skip ); i_skip += 2;
707
708 //        i_packet_size_left = i_packet_length;   // XXX données reellement lu
709     /* FIXME I have to do that for some file, I don't known why */
710     i_packet_size_left = i_data_packet_min;
711
712     if( b_packet_multiple_payload )
713     {
714         i_payload_count = p_peek[i_skip] & 0x3f;
715         i_payload_length_type = ( p_peek[i_skip] >> 6 )&0x03;
716         i_skip++;
717     }
718     else
719     {
720         i_payload_count = 1;
721         i_payload_length_type = 0x02; // unused
722     }
723
724     for( i_payload = 0; i_payload < i_payload_count ; i_payload++ )
725     {
726         asf_stream_t   *p_stream;
727
728         int i_stream_number;
729         int i_media_object_number;
730         int i_media_object_offset;
731         int i_replicated_data_length;
732         int i_payload_data_length;
733         int i_payload_data_pos;
734         int i_sub_payload_data_length;
735         int i_tmp;
736
737         mtime_t i_pts;
738         mtime_t i_pts_delta;
739
740         if( i_skip >= i_packet_size_left )
741         {
742             /* prevent some segfault with invalid file */
743             break;
744         }
745
746         i_stream_number = p_peek[i_skip] & 0x7f;
747         i_skip++;
748
749         GETVALUE2b( i_packet_property >> 4, i_media_object_number, 0 );
750         GETVALUE2b( i_packet_property >> 2, i_tmp, 0 );
751         GETVALUE2b( i_packet_property, i_replicated_data_length, 0 );
752
753         if( i_replicated_data_length > 1 ) // should be at least 8 bytes
754         {
755             i_pts = (mtime_t)GetDWLE( p_peek + i_skip + 4 ) * 1000;
756             i_skip += i_replicated_data_length;
757             i_pts_delta = 0;
758
759             i_media_object_offset = i_tmp;
760
761             if( i_skip >= i_packet_size_left )
762             {
763                 break;
764             }
765         }
766         else if( i_replicated_data_length == 1 )
767         {
768
769             msg_Dbg( p_input, "found compressed payload" );
770
771             i_pts = (mtime_t)i_tmp * 1000;
772             i_pts_delta = (mtime_t)p_peek[i_skip] * 1000; i_skip++;
773
774             i_media_object_offset = 0;
775         }
776         else
777         {
778             i_pts = (mtime_t)i_packet_send_time * 1000;
779             i_pts_delta = 0;
780
781             i_media_object_offset = i_tmp;
782         }
783
784         i_pts = __MAX( i_pts - p_sys->p_fp->i_preroll * 1000, 0 );
785         if( b_packet_multiple_payload )
786         {
787             GETVALUE2b( i_payload_length_type, i_payload_data_length, 0 );
788         }
789         else
790         {
791             i_payload_data_length = i_packet_length -
792                                         i_packet_padding_length - i_skip;
793         }
794
795         if( i_payload_data_length < 0 || i_skip + i_payload_data_length > i_packet_size_left )
796         {
797             break;
798         }
799
800 #if 0
801          msg_Dbg( p_input,
802                   "payload(%d/%d) stream_number:%d media_object_number:%d media_object_offset:%d replicated_data_length:%d payload_data_length %d",
803                   i_payload + 1,
804                   i_payload_count,
805                   i_stream_number,
806                   i_media_object_number,
807                   i_media_object_offset,
808                   i_replicated_data_length,
809                   i_payload_data_length );
810 #endif
811
812         if( !( p_stream = p_sys->stream[i_stream_number] ) )
813         {
814             msg_Warn( p_input,
815                       "undeclared stream[Id 0x%x]", i_stream_number );
816             i_skip += i_payload_data_length;
817             continue;   // over payload
818         }
819
820         if( !p_stream->p_es || !p_stream->p_es->p_decoder_fifo )
821         {
822             i_skip += i_payload_data_length;
823             continue;
824         }
825
826
827         for( i_payload_data_pos = 0;
828              i_payload_data_pos < i_payload_data_length &&
829                     i_packet_size_left > 0;
830              i_payload_data_pos += i_sub_payload_data_length )
831         {
832             data_packet_t  *p_data;
833             int i_read;
834             // read sub payload length
835             if( i_replicated_data_length == 1 )
836             {
837                 i_sub_payload_data_length = p_peek[i_skip]; i_skip++;
838                 i_payload_data_pos++;
839             }
840             else
841             {
842                 i_sub_payload_data_length = i_payload_data_length;
843             }
844
845             /* FIXME I don't use i_media_object_number, sould I ? */
846             if( p_stream->p_pes && i_media_object_offset == 0 )
847             {
848                 /* send complete packet to decoder */
849                 if( p_stream->p_pes->i_pes_size > 0 )
850                 {
851                     if( p_stream->p_es->p_decoder_fifo &&
852                         ( b_play_audio || p_stream->i_cat != AUDIO_ES ) )
853                     {
854                         p_stream->p_pes->i_rate =
855                             p_input->stream.control.i_rate;
856                         input_DecodePES( p_stream->p_es->p_decoder_fifo,
857                                          p_stream->p_pes );
858                     }
859                     else
860                     {
861                         input_DeletePES( p_input->p_method_data,
862                                          p_stream->p_pes );
863                     }
864                     p_stream->p_pes = NULL;
865                 }
866             }
867
868             if( !p_stream->p_pes )  // add a new PES
869             {
870                 p_stream->i_time =
871                     ( (mtime_t)i_pts + i_payload * (mtime_t)i_pts_delta );
872
873                 p_stream->p_pes = input_NewPES( p_input->p_method_data );
874                 p_stream->p_pes->i_dts =
875                     p_stream->p_pes->i_pts =
876                         input_ClockGetTS( p_input,
877                                           p_input->stream.p_selected_program,
878                                           p_stream->i_time * 9 /100 );
879
880                 //msg_Err( p_input, "stream[0x%2x] pts=%lld", i_stream_number, p_stream->p_pes->i_pts );
881                 p_stream->p_pes->p_next = NULL;
882                 p_stream->p_pes->i_nb_data = 0;
883                 p_stream->p_pes->i_pes_size = 0;
884             }
885
886             i_read = i_sub_payload_data_length + i_skip;
887             if((p_data = stream_DataPacket( p_sys->s,i_read,VLC_TRUE)) == NULL)
888             {
889                 msg_Warn( p_input, "cannot read data" );
890                 return( 0 );
891             }
892             p_data->p_payload_start += i_skip;
893             i_packet_size_left -= i_read;
894
895
896             if( !p_stream->p_pes->p_first )
897             {
898                 p_stream->p_pes->p_first = p_stream->p_pes->p_last = p_data;
899             }
900             else
901             {
902                 p_stream->p_pes->p_last->p_next = p_data;
903                 p_stream->p_pes->p_last = p_data;
904             }
905             p_stream->p_pes->i_pes_size += i_sub_payload_data_length;
906             p_stream->p_pes->i_nb_data++;
907
908             i_skip = 0;
909             if( i_packet_size_left > 0 )
910             {
911                 if( stream_Peek( p_sys->s, &p_peek, i_packet_size_left ) < i_packet_size_left )
912                 {
913                     // EOF ?
914                     msg_Warn( p_input, "cannot peek, EOF ?" );
915                     return( 0 );
916                 }
917             }
918         }
919     }
920
921     if( i_packet_size_left > 0 )
922     {
923         if( stream_Read( p_sys->s, NULL, i_packet_size_left ) < i_packet_size_left )
924         {
925             msg_Warn( p_input, "cannot skip data, EOF ?" );
926             return( 0 );
927         }
928     }
929
930     return( 1 );
931
932 loop_error_recovery:
933     msg_Warn( p_input, "unsupported packet header" );
934     if( p_sys->p_fp->i_min_data_packet_size != p_sys->p_fp->i_max_data_packet_size )
935     {
936         msg_Err( p_input, "unsupported packet header, fatal error" );
937         return( -1 );
938     }
939     stream_Read( p_sys->s, NULL, i_data_packet_min );
940
941     return( 1 );
942 }
943
944