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