]> git.sesse.net Git - vlc/blob - modules/demux/asf/asf.c
6118a23a97e542e3a5fde15b2b5a6a1a6b79fbfb
[vlc] / 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.36 2003/08/25 23:36:16 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_Seek( p_sys->s, 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 = stream_Size( p_sys->s );
338
339         if( p_sys->i_data_end > 0 && i_size > p_sys->i_data_end )
340         {
341             i_size = p_sys->i_data_end;
342         }
343
344         /* real number of packets */
345         i_count = ( i_size - p_sys->i_data_begin ) /
346                   p_sys->p_fp->i_min_data_packet_size;
347
348         /* calculate the time duration in micro-s */
349         p_sys->i_length = (mtime_t)p_sys->p_fp->i_play_duration / 10 *
350                    (mtime_t)i_count /
351                    (mtime_t)p_sys->p_fp->i_data_packets_count;
352
353         if( p_sys->i_length > 0 )
354         {
355             p_input->stream.i_mux_rate =
356                 i_size / 50 * (int64_t)1000000 / p_sys->i_length;
357         }
358     }
359
360     vlc_mutex_lock( &p_input->stream.stream_lock );
361     p_input->stream.p_selected_program->b_is_ok = 1;
362     vlc_mutex_unlock( &p_input->stream.stream_lock );
363
364
365     /* We add all info about this stream */
366     p_cat = input_InfoCategory( p_input, "Asf" );
367     if( p_sys->i_length > 0 )
368     {
369         int64_t i_second = p_sys->i_length / (int64_t)1000000;
370
371         input_AddInfo( p_cat, _("Length"), "%d:%d:%d",
372                        (int)(i_second / 36000),
373                        (int)(( i_second / 60 ) % 60),
374                        (int)(i_second % 60) );
375     }
376     input_AddInfo( p_cat, _("Number of streams"), "%d" , p_sys->i_streams );
377
378     if( ( p_cd = ASF_FindObject( p_sys->p_root->p_hdr,
379                                  &asf_object_content_description_guid, 0 ) ) )
380     {
381         if( *p_cd->psz_title )
382             input_AddInfo( p_cat, _("Title"), p_cd->psz_title );
383         if( p_cd->psz_author )
384             input_AddInfo( p_cat, _("Author"), p_cd->psz_author );
385         if( p_cd->psz_copyright )
386             input_AddInfo( p_cat, _("Copyright"), p_cd->psz_copyright );
387         if( *p_cd->psz_description )
388             input_AddInfo( p_cat, _("Description"), p_cd->psz_description );
389         if( *p_cd->psz_rating )
390             input_AddInfo( p_cat, _("Rating"), p_cd->psz_rating );
391     }
392
393     for( i_stream = 0, i = 0; i < 128; i++ )
394     {
395         asf_stream_t *tk =  p_sys->stream[i];
396         asf_object_codec_list_t *p_cl =
397             ASF_FindObject( p_sys->p_root->p_hdr,
398                             &asf_object_codec_list_guid, 0 );
399         char psz_cat[sizeof(_("Stream "))+10];
400
401         if( p_sys->stream[i] == NULL )
402         {
403             continue;
404         }
405         sprintf( psz_cat, _("Stream %d"), i_stream );
406         p_cat = input_InfoCategory( p_input, psz_cat);
407
408         input_AddInfo( p_cat, _("Type"),
409                        ( tk->i_cat == AUDIO_ES ? _("Audio") : _("Video") ) );
410         input_AddInfo( p_cat, _("Codec"), "%.4s",
411                            (char*)&tk->p_es->i_fourcc );
412         if( p_cl && i_stream < p_cl->i_codec_entries_count )
413         {
414             input_AddInfo( p_cat, _("Codec name"),
415                            p_cl->codec[i_stream].psz_name );
416             input_AddInfo( p_cat, _("Codec description"),
417                            p_cl->codec[i_stream].psz_description );
418         }
419
420         if( tk->i_cat == AUDIO_ES && tk->p_es->p_waveformatex )
421         {
422             WAVEFORMATEX    *p_wf = tk->p_es->p_waveformatex;
423             input_AddInfo( p_cat, _("Channels"), "%d", p_wf->nChannels );
424             input_AddInfo( p_cat, _("Sample Rate"), "%d", p_wf->nSamplesPerSec );
425             input_AddInfo( p_cat, _("Avg. byterate"), "%d", p_wf->nAvgBytesPerSec );
426             input_AddInfo( p_cat, _("Bits Per Sample"), "%d", p_wf->wBitsPerSample );
427         }
428         else if( tk->i_cat == VIDEO_ES && tk->p_es->p_bitmapinfoheader )
429         {
430             BITMAPINFOHEADER *p_bih = tk->p_es->p_bitmapinfoheader;
431
432             input_AddInfo( p_cat, _("Resolution"), "%dx%d",
433                            p_bih->biWidth, p_bih->biHeight );
434             input_AddInfo( p_cat, _("Planes"), "%d", p_bih->biPlanes );
435             input_AddInfo( p_cat, _("Bits Per Pixel"), "%d", p_bih->biBitCount );
436             input_AddInfo( p_cat, _("Image Size"), "%d", p_bih->biSizeImage );
437             input_AddInfo( p_cat, _("X pixels per meter"), "%d",
438                            p_bih->biXPelsPerMeter );
439             input_AddInfo( p_cat, _("Y pixels per meter"), "%d",
440                            p_bih->biYPelsPerMeter );
441         }
442
443         i_stream++;
444     }
445
446     return VLC_SUCCESS;
447
448 error:
449     ASF_FreeObjectRoot( p_sys->s, p_sys->p_root );
450     stream_Release( p_sys->s );
451     free( p_sys );
452     return VLC_EGENERIC;
453 }
454
455
456 /*****************************************************************************
457  * Demux: read packet and send them to decoders
458  *****************************************************************************/
459 static int Demux( input_thread_t *p_input )
460 {
461     demux_sys_t *p_sys = p_input->p_demux_data;
462     vlc_bool_t b_play_audio;
463     int i;
464     vlc_bool_t b_stream;
465
466     b_stream = VLC_FALSE;
467     for( i = 0; i < 128; i++ )
468     {
469         if( p_sys->stream[i] &&
470             p_sys->stream[i]->p_es &&
471             p_sys->stream[i]->p_es->p_decoder_fifo )
472         {
473             b_stream = VLC_TRUE;
474         }
475     }
476     if( !b_stream )
477     {
478         msg_Warn( p_input, "no stream selected, exiting..." );
479         return( 0 );
480     }
481
482     /* catch seek from user */
483     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
484     {
485         int64_t i_offset;
486
487         msleep( p_input->i_pts_delay );
488
489         i_offset = stream_Tell( p_sys->s ) - p_sys->i_data_begin;
490         if( i_offset  < 0 )
491         {
492             i_offset = 0;
493         }
494         if( i_offset % p_sys->p_fp->i_min_data_packet_size > 0 )
495         {
496             i_offset -= i_offset % p_sys->p_fp->i_min_data_packet_size;
497         }
498
499         if( stream_Seek( p_sys->s, i_offset + p_sys->i_data_begin ) )
500         {
501             msg_Warn( p_input, "cannot resynch after seek (EOF?)" );
502             return -1;
503         }
504
505         p_sys->i_time = -1;
506         for( i = 0; i < 128 ; i++ )
507         {
508 #define p_stream p_sys->stream[i]
509             if( p_stream )
510             {
511                 p_stream->i_time = -1;
512             }
513 #undef p_stream
514         }
515     }
516
517     /* Check if we need to send the audio data to decoder */
518     b_play_audio = !p_input->stream.control.b_mute;
519
520     for( ;; )
521     {
522         mtime_t i_length;
523         mtime_t i_time_begin = GetMoviePTS( p_sys );
524         int i_result;
525
526         if( p_input->b_die )
527         {
528             break;
529         }
530
531         if( ( i_result = DemuxPacket( p_input, b_play_audio ) ) <= 0 )
532         {
533             return i_result;
534         }
535         if( i_time_begin == -1 )
536         {
537             i_time_begin = GetMoviePTS( p_sys );
538         }
539         else
540         {
541             i_length = GetMoviePTS( p_sys ) - i_time_begin;
542             if( i_length < 0 || i_length >= 40 * 1000 )
543             {
544                 break;
545             }
546         }
547     }
548
549     p_sys->i_time = GetMoviePTS( p_sys );
550     if( p_sys->i_time >= 0 )
551     {
552         input_ClockManageRef( p_input,
553                               p_input->stream.p_selected_program,
554                               p_sys->i_time * 9 / 100 );
555     }
556
557     return( 1 );
558 }
559
560 /*****************************************************************************
561  * Close: frees unused data
562  *****************************************************************************/
563 static void Close( vlc_object_t * p_this )
564 {
565     input_thread_t *p_input = (input_thread_t *)p_this;
566     demux_sys_t    *p_sys = p_input->p_demux_data;
567     int i_stream;
568
569     msg_Dbg( p_input, "Freeing all memory" );
570
571     ASF_FreeObjectRoot( p_sys->s, p_sys->p_root );
572     for( i_stream = 0; i_stream < 128; i_stream++ )
573     {
574 #define p_stream p_sys->stream[i_stream]
575         if( p_stream )
576         {
577             if( p_stream->p_pes )
578             {
579                 input_DeletePES( p_input->p_method_data, p_stream->p_pes );
580             }
581             free( p_stream );
582         }
583 #undef p_stream
584     }
585     stream_Release( p_sys->s );
586     free( p_sys );
587 }
588
589
590 /*****************************************************************************
591  *
592  *****************************************************************************/
593 static mtime_t GetMoviePTS( demux_sys_t *p_sys )
594 {
595     mtime_t i_time;
596     int     i_stream;
597
598     i_time = -1;
599     for( i_stream = 0; i_stream < 128 ; i_stream++ )
600     {
601 #define p_stream p_sys->stream[i_stream]
602         if( p_stream && p_stream->p_es && p_stream->p_es->p_decoder_fifo && p_stream->i_time > 0)
603         {
604             if( i_time < 0 )
605             {
606                 i_time = p_stream->i_time;
607             }
608             else
609             {
610                 i_time = __MIN( i_time, p_stream->i_time );
611             }
612         }
613 #undef p_stream
614     }
615
616     return( i_time );
617 }
618
619 #define GETVALUE2b( bits, var, def ) \
620     switch( (bits)&0x03 ) \
621     { \
622         case 1: var = p_peek[i_skip]; i_skip++; break; \
623         case 2: var = GetWLE( p_peek + i_skip );  i_skip+= 2; break; \
624         case 3: var = GetDWLE( p_peek + i_skip ); i_skip+= 4; break; \
625         case 0: \
626         default: var = def; break;\
627     }
628
629 static int DemuxPacket( input_thread_t *p_input, vlc_bool_t b_play_audio )
630 {
631     demux_sys_t *p_sys = p_input->p_demux_data;
632     int     i_data_packet_min = p_sys->p_fp->i_min_data_packet_size;
633     uint8_t *p_peek;
634     int     i_skip;
635
636     int     i_packet_size_left;
637     int     i_packet_flags;
638     int     i_packet_property;
639
640     int     b_packet_multiple_payload;
641     int     i_packet_length;
642     int     i_packet_sequence;
643     int     i_packet_padding_length;
644
645     uint32_t    i_packet_send_time;
646     uint16_t    i_packet_duration;
647     int         i_payload;
648     int         i_payload_count;
649     int         i_payload_length_type;
650
651
652     if( stream_Peek( p_sys->s, &p_peek, i_data_packet_min ) < i_data_packet_min )
653     {
654         // EOF ?
655         msg_Warn( p_input, "cannot peek while getting new packet, EOF ?" );
656         return( 0 );
657     }
658     i_skip = 0;
659
660     /* *** parse error correction if present *** */
661     if( p_peek[0]&0x80 )
662     {
663         unsigned int i_error_correction_length_type;
664         unsigned int i_error_correction_data_length;
665         unsigned int i_opaque_data_present;
666
667         i_error_correction_data_length = p_peek[0] & 0x0f;  // 4bits
668         i_opaque_data_present = ( p_peek[0] >> 4 )& 0x01;    // 1bit
669         i_error_correction_length_type = ( p_peek[0] >> 5 ) & 0x03; // 2bits
670         i_skip += 1; // skip error correction flags
671
672         if( i_error_correction_length_type != 0x00 ||
673             i_opaque_data_present != 0 ||
674             i_error_correction_data_length != 0x02 )
675         {
676             goto loop_error_recovery;
677         }
678
679         i_skip += i_error_correction_data_length;
680     }
681     else
682     {
683         msg_Warn( p_input, "p_peek[0]&0x80 != 0x80" );
684     }
685
686     /* sanity check */
687     if( i_skip + 2 >= i_data_packet_min )
688     {
689         goto loop_error_recovery;
690     }
691
692     i_packet_flags = p_peek[i_skip]; i_skip++;
693     i_packet_property = p_peek[i_skip]; i_skip++;
694
695     b_packet_multiple_payload = i_packet_flags&0x01;
696
697     /* read some value */
698     GETVALUE2b( i_packet_flags >> 5, i_packet_length, i_data_packet_min );
699     GETVALUE2b( i_packet_flags >> 1, i_packet_sequence, 0 );
700     GETVALUE2b( i_packet_flags >> 3, i_packet_padding_length, 0 );
701
702     i_packet_send_time = GetDWLE( p_peek + i_skip ); i_skip += 4;
703     i_packet_duration  = GetWLE( p_peek + i_skip ); i_skip += 2;
704
705 //        i_packet_size_left = i_packet_length;   // XXX données reellement lu
706     /* FIXME I have to do that for some file, I don't known why */
707     i_packet_size_left = i_data_packet_min;
708
709     if( b_packet_multiple_payload )
710     {
711         i_payload_count = p_peek[i_skip] & 0x3f;
712         i_payload_length_type = ( p_peek[i_skip] >> 6 )&0x03;
713         i_skip++;
714     }
715     else
716     {
717         i_payload_count = 1;
718         i_payload_length_type = 0x02; // unused
719     }
720
721     for( i_payload = 0; i_payload < i_payload_count ; i_payload++ )
722     {
723         asf_stream_t   *p_stream;
724
725         int i_stream_number;
726         int i_media_object_number;
727         int i_media_object_offset;
728         int i_replicated_data_length;
729         int i_payload_data_length;
730         int i_payload_data_pos;
731         int i_sub_payload_data_length;
732         int i_tmp;
733
734         mtime_t i_pts;
735         mtime_t i_pts_delta;
736
737         if( i_skip >= i_packet_size_left )
738         {
739             /* prevent some segfault with invalid file */
740             break;
741         }
742
743         i_stream_number = p_peek[i_skip] & 0x7f;
744         i_skip++;
745
746         GETVALUE2b( i_packet_property >> 4, i_media_object_number, 0 );
747         GETVALUE2b( i_packet_property >> 2, i_tmp, 0 );
748         GETVALUE2b( i_packet_property, i_replicated_data_length, 0 );
749
750         if( i_replicated_data_length > 1 ) // should be at least 8 bytes
751         {
752             i_pts = (mtime_t)GetDWLE( p_peek + i_skip + 4 ) * 1000;
753             i_skip += i_replicated_data_length;
754             i_pts_delta = 0;
755
756             i_media_object_offset = i_tmp;
757
758             if( i_skip >= i_packet_size_left )
759             {
760                 break;
761             }
762         }
763         else if( i_replicated_data_length == 1 )
764         {
765
766             msg_Dbg( p_input, "found compressed payload" );
767
768             i_pts = (mtime_t)i_tmp * 1000;
769             i_pts_delta = (mtime_t)p_peek[i_skip] * 1000; i_skip++;
770
771             i_media_object_offset = 0;
772         }
773         else
774         {
775             i_pts = (mtime_t)i_packet_send_time * 1000;
776             i_pts_delta = 0;
777
778             i_media_object_offset = i_tmp;
779         }
780
781         i_pts = __MAX( i_pts - p_sys->p_fp->i_preroll * 1000, 0 );
782         if( b_packet_multiple_payload )
783         {
784             GETVALUE2b( i_payload_length_type, i_payload_data_length, 0 );
785         }
786         else
787         {
788             i_payload_data_length = i_packet_length -
789                                         i_packet_padding_length - i_skip;
790         }
791
792         if( i_payload_data_length < 0 || i_skip + i_payload_data_length > i_packet_size_left )
793         {
794             break;
795         }
796
797 #if 0
798          msg_Dbg( p_input,
799                   "payload(%d/%d) stream_number:%d media_object_number:%d media_object_offset:%d replicated_data_length:%d payload_data_length %d",
800                   i_payload + 1,
801                   i_payload_count,
802                   i_stream_number,
803                   i_media_object_number,
804                   i_media_object_offset,
805                   i_replicated_data_length,
806                   i_payload_data_length );
807 #endif
808
809         if( !( p_stream = p_sys->stream[i_stream_number] ) )
810         {
811             msg_Warn( p_input,
812                       "undeclared stream[Id 0x%x]", i_stream_number );
813             i_skip += i_payload_data_length;
814             continue;   // over payload
815         }
816
817         if( !p_stream->p_es || !p_stream->p_es->p_decoder_fifo )
818         {
819             i_skip += i_payload_data_length;
820             continue;
821         }
822
823
824         for( i_payload_data_pos = 0;
825              i_payload_data_pos < i_payload_data_length &&
826                     i_packet_size_left > 0;
827              i_payload_data_pos += i_sub_payload_data_length )
828         {
829             data_packet_t  *p_data;
830             int i_read;
831             // read sub payload length
832             if( i_replicated_data_length == 1 )
833             {
834                 i_sub_payload_data_length = p_peek[i_skip]; i_skip++;
835                 i_payload_data_pos++;
836             }
837             else
838             {
839                 i_sub_payload_data_length = i_payload_data_length;
840             }
841
842             /* FIXME I don't use i_media_object_number, sould I ? */
843             if( p_stream->p_pes && i_media_object_offset == 0 )
844             {
845                 /* send complete packet to decoder */
846                 if( p_stream->p_pes->i_pes_size > 0 )
847                 {
848                     if( p_stream->p_es->p_decoder_fifo &&
849                         ( b_play_audio || p_stream->i_cat != AUDIO_ES ) )
850                     {
851                         p_stream->p_pes->i_rate =
852                             p_input->stream.control.i_rate;
853                         input_DecodePES( p_stream->p_es->p_decoder_fifo,
854                                          p_stream->p_pes );
855                     }
856                     else
857                     {
858                         input_DeletePES( p_input->p_method_data,
859                                          p_stream->p_pes );
860                     }
861                     p_stream->p_pes = NULL;
862                 }
863             }
864
865             if( !p_stream->p_pes )  // add a new PES
866             {
867                 p_stream->i_time =
868                     ( (mtime_t)i_pts + i_payload * (mtime_t)i_pts_delta );
869
870                 p_stream->p_pes = input_NewPES( p_input->p_method_data );
871                 p_stream->p_pes->i_dts =
872                     p_stream->p_pes->i_pts =
873                         input_ClockGetTS( p_input,
874                                           p_input->stream.p_selected_program,
875                                           p_stream->i_time * 9 /100 );
876
877                 //msg_Err( p_input, "stream[0x%2x] pts=%lld", i_stream_number, p_stream->p_pes->i_pts );
878                 p_stream->p_pes->p_next = NULL;
879                 p_stream->p_pes->i_nb_data = 0;
880                 p_stream->p_pes->i_pes_size = 0;
881             }
882
883             i_read = i_sub_payload_data_length + i_skip;
884             if((p_data = stream_DataPacket( p_sys->s,i_read,VLC_TRUE)) == NULL)
885             {
886                 msg_Warn( p_input, "cannot read data" );
887                 return( 0 );
888             }
889             p_data->p_payload_start += i_skip;
890             i_packet_size_left -= i_read;
891
892
893             if( !p_stream->p_pes->p_first )
894             {
895                 p_stream->p_pes->p_first = p_stream->p_pes->p_last = p_data;
896             }
897             else
898             {
899                 p_stream->p_pes->p_last->p_next = p_data;
900                 p_stream->p_pes->p_last = p_data;
901             }
902             p_stream->p_pes->i_pes_size += i_sub_payload_data_length;
903             p_stream->p_pes->i_nb_data++;
904
905             i_skip = 0;
906             if( i_packet_size_left > 0 )
907             {
908                 if( stream_Peek( p_sys->s, &p_peek, i_packet_size_left ) < i_packet_size_left )
909                 {
910                     // EOF ?
911                     msg_Warn( p_input, "cannot peek, EOF ?" );
912                     return( 0 );
913                 }
914             }
915         }
916     }
917
918     if( i_packet_size_left > 0 )
919     {
920         if( stream_Read( p_sys->s, NULL, i_packet_size_left ) < i_packet_size_left )
921         {
922             msg_Warn( p_input, "cannot skip data, EOF ?" );
923             return( 0 );
924         }
925     }
926
927     return( 1 );
928
929 loop_error_recovery:
930     msg_Warn( p_input, "unsupported packet header" );
931     if( p_sys->p_fp->i_min_data_packet_size != p_sys->p_fp->i_max_data_packet_size )
932     {
933         msg_Err( p_input, "unsupported packet header, fatal error" );
934         return( -1 );
935     }
936     stream_Read( p_sys->s, NULL, i_data_packet_min );
937
938     return( 1 );
939 }
940
941