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