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