]> git.sesse.net Git - vlc/blob - modules/demux/avi/avi.c
* all: Fix an other (and last ? ;) endian issue.
[vlc] / modules / demux / avi / avi.c
1 /*****************************************************************************
2  * avi.c : AVI file Stream input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: avi.c,v 1.16 2002/12/04 15:47:31 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 "video.h"
35
36 #include "libavi.h"
37
38 #define __AVI_SUBTITLE__ 1
39
40 #ifdef __AVI_SUBTITLE__
41 #   include "../util/sub.h"
42 #endif
43 #include "avi.h"
44
45 /*****************************************************************************
46  * Local prototypes
47  *****************************************************************************/
48 static int    AVIInit   ( vlc_object_t * );
49 static void __AVIEnd    ( vlc_object_t * );
50 static int    AVISeek   ( input_thread_t *, mtime_t, int );
51 static int    AVIDemux_Seekable  ( input_thread_t * );
52 static int    AVIDemux_UnSeekable( input_thread_t *p_input );
53
54 #define AVIEnd(a) __AVIEnd(VLC_OBJECT(a))
55
56 /*****************************************************************************
57  * Module descriptor
58  *****************************************************************************/
59 vlc_module_begin();
60     add_category_hint( "demuxer", NULL );
61         add_bool( "avi-interleaved", 0, NULL,
62                   "force interleaved method", 
63                   "force interleaved method" );
64         add_bool( "avi-index", 0, NULL,
65                   "force index creation", 
66                   "force index creation" );
67
68     set_description( "avi demuxer" );
69     set_capability( "demux", 212 );
70     set_callbacks( AVIInit, __AVIEnd );
71 vlc_module_end();
72
73 /*****************************************************************************
74  * Some useful functions to manipulate memory 
75  *****************************************************************************/
76
77 static uint16_t GetWLE( uint8_t *p_buff )
78 {
79     return (uint16_t)p_buff[0] | ( ((uint16_t)p_buff[1]) << 8 );
80 }
81
82 static uint32_t GetDWLE( uint8_t *p_buff )
83 {
84     return (uint32_t)p_buff[0] | ( ((uint32_t)p_buff[1]) << 8 ) |
85             ( ((uint32_t)p_buff[2]) << 16 ) | ( ((uint32_t)p_buff[3]) << 24 );
86 }
87
88 static uint32_t GetDWBE( uint8_t *p_buff )
89 {
90     return (uint32_t)p_buff[3] | ( ((uint32_t)p_buff[2]) << 8 ) |
91             ( ((uint32_t)p_buff[1]) << 16 ) | ( ((uint32_t)p_buff[0]) << 24 );
92 }
93 static vlc_fourcc_t GetFOURCC( byte_t *p_buff )
94 {
95     return VLC_FOURCC( p_buff[0], p_buff[1], p_buff[2], p_buff[3] );
96 }
97
98 static inline off_t __EVEN( off_t i )
99 {
100     return (i & 1) ? i + 1 : i;
101 }
102
103 #define __ABS( x ) ( (x) < 0 ? (-(x)) : (x) )
104
105 /* read data in a pes */
106 static int input_ReadInPES( input_thread_t *p_input, 
107                             pes_packet_t **pp_pes, 
108                             int i_size )
109 {
110     pes_packet_t *p_pes;
111     data_packet_t *p_data;
112
113     
114     if( !(p_pes = input_NewPES( p_input->p_method_data ) ) )
115     {
116         pp_pes = NULL;
117         return -1;
118     }
119
120     *pp_pes = p_pes;
121
122     if( !i_size )
123     {
124         p_pes->p_first = 
125             p_pes->p_last  = 
126                 input_NewPacket( p_input->p_method_data, 0 );
127         p_pes->i_nb_data = 1;
128         p_pes->i_pes_size = 0;
129         return 0;
130     }
131     
132     p_pes->i_nb_data = 0;
133     p_pes->i_pes_size = 0;
134
135     while( p_pes->i_pes_size < i_size )
136     {
137         int i_read;
138
139         i_read = input_SplitBuffer(p_input, 
140                                    &p_data, 
141                                    __MIN( i_size - 
142                                           p_pes->i_pes_size, 1024 ) );
143         if( i_read <= 0 )
144         {
145             return p_pes->i_pes_size;
146         }
147         
148         if( !p_pes->p_first )
149         {
150             p_pes->p_first = p_data;
151         }
152         else
153         {
154             p_pes->p_last->p_next = p_data;
155         }
156         p_pes->p_last = p_data;
157         p_pes->i_nb_data++;
158         p_pes->i_pes_size += i_read;
159     } 
160
161
162     return p_pes->i_pes_size;
163 }
164
165 /* Test if it seems that it's a key frame */
166 static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, uint8_t *p_byte )
167 {
168     switch( i_fourcc )
169     {
170         case FOURCC_DIV1:
171             /* we have:
172              *  startcode:      0x00000100   32bits
173              *  framenumber     ?             5bits
174              *  piture type     0(I),1(P)     2bits
175              */
176             if( GetDWBE( p_byte ) != 0x00000100 ) 
177             {
178                 /* it's not an msmpegv1 stream, strange...*/
179                 return AVIIF_KEYFRAME;
180             }
181             else
182             {
183                 return p_byte[4] & 0x06 ? 0 : AVIIF_KEYFRAME;
184             }
185         case FOURCC_DIV2:
186         case FOURCC_DIV3:   // wmv1 also
187             /* we have
188              *  picture type    0(I),1(P)     2bits
189              */
190             return p_byte[0] & 0xC0 ? 0 : AVIIF_KEYFRAME;
191         case FOURCC_mp4v:
192             /* we should find first occurence of 0x000001b6 (32bits)
193              *  startcode:      0x000001b6   32bits
194              *  piture type     0(I),1(P)     2bits
195              */
196             if( GetDWBE( p_byte ) != 0x000001b6 )
197             {
198                 /* not true , need to find the first VOP header */
199                 return AVIIF_KEYFRAME;
200             }
201             else
202             {
203                 return p_byte[4] & 0xC0 ? 0 : AVIIF_KEYFRAME;
204             }
205         default:
206             /* I can't do it, so say yes */
207             return AVIIF_KEYFRAME;
208     }
209 }
210
211 vlc_fourcc_t AVI_FourccGetCodec( int i_cat, vlc_fourcc_t i_codec )
212 {
213     switch( i_cat )
214     {
215         case AUDIO_ES:
216             switch( i_codec )
217             {
218                 case WAVE_FORMAT_PCM:
219                     return VLC_FOURCC( 'a', 'r', 'a', 'w' );
220                 case WAVE_FORMAT_MPEG:
221                 case WAVE_FORMAT_MPEGLAYER3:
222                     return VLC_FOURCC( 'm', 'p', 'g', 'a' );
223                 case WAVE_FORMAT_A52:
224                     return VLC_FOURCC( 'a', '5', '2', ' ' );
225                 case WAVE_FORMAT_WMA1:
226                     return VLC_FOURCC( 'w', 'm', 'a', '1' );
227                 case WAVE_FORMAT_WMA2:
228                     return VLC_FOURCC( 'w', 'm', 'a', '2' );
229                 default:
230                     return VLC_FOURCC( 'm', 's', 
231                                        ( i_codec >> 8 )&0xff, i_codec&0xff );
232             }
233         case VIDEO_ES:
234             // XXX DIV1 <- msmpeg4v1, DIV2 <- msmpeg4v2, DIV3 <- msmpeg4v3, mp4v for mpeg4 
235             switch( i_codec )
236             {
237                 case FOURCC_DIV1:
238                 case FOURCC_div1:
239                 case FOURCC_MPG4:
240                 case FOURCC_mpg4:
241                     return FOURCC_DIV1;
242                 case FOURCC_DIV2:
243                 case FOURCC_div2:
244                 case FOURCC_MP42:
245                 case FOURCC_mp42:
246                 case FOURCC_MPG3:
247                 case FOURCC_mpg3:
248                     return FOURCC_DIV2;
249                 case FOURCC_div3:
250                 case FOURCC_MP43:
251                 case FOURCC_mp43:
252                 case FOURCC_DIV3:
253                 case FOURCC_DIV4:
254                 case FOURCC_div4:
255                 case FOURCC_DIV5:
256                 case FOURCC_div5:
257                 case FOURCC_DIV6:
258                 case FOURCC_div6:
259                 case FOURCC_AP41:
260                 case FOURCC_3IV1:
261                     return FOURCC_DIV3;
262                 case FOURCC_DIVX:
263                 case FOURCC_divx:
264                 case FOURCC_MP4S:
265                 case FOURCC_mp4s:
266                 case FOURCC_M4S2:
267                 case FOURCC_m4s2:
268                 case FOURCC_xvid:
269                 case FOURCC_XVID:
270                 case FOURCC_XviD:
271                 case FOURCC_DX50:
272                 case FOURCC_mp4v:
273                 case FOURCC_4:
274                     return FOURCC_mp4v;
275             }
276         default:
277             return VLC_FOURCC( 'u', 'n', 'd', 'f' );
278     }
279 }
280
281 static void AVI_ParseStreamHeader( vlc_fourcc_t i_id,
282                                    int *pi_number, int *pi_type )
283 {
284 #define SET_PTR( p, v ) if( p ) *(p) = (v);
285     int c1, c2;
286
287     c1 = ((uint8_t *)&i_id)[0];
288     c2 = ((uint8_t *)&i_id)[1];
289
290     if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
291     {
292         SET_PTR( pi_number, 100 ); /* > max stream number */
293         SET_PTR( pi_type, UNKNOWN_ES );
294     }
295     else
296     {
297         SET_PTR( pi_number, (c1 - '0') * 10 + (c2 - '0' ) );
298         switch( VLC_TWOCC( ((uint8_t *)&i_id)[2], ((uint8_t *)&i_id)[3] ) )
299         {
300             case AVITWOCC_wb:
301                 SET_PTR( pi_type, AUDIO_ES );
302                 break;
303             case AVITWOCC_dc:
304             case AVITWOCC_db:
305                 SET_PTR( pi_type, VIDEO_ES );
306                 break;
307             default:
308                 SET_PTR( pi_type, UNKNOWN_ES );
309                 break;
310         }
311     }
312 #undef SET_PTR
313 }
314
315 static int AVI_PacketGetHeader( input_thread_t *p_input, avi_packet_t *p_pk )
316 {
317     uint8_t  *p_peek;
318     
319     if( input_Peek( p_input, &p_peek, 16 ) < 16 )
320     {
321         return VLC_EGENERIC;
322     }
323     p_pk->i_fourcc  = GetFOURCC( p_peek );
324     p_pk->i_size    = GetDWLE( p_peek + 4 );
325     p_pk->i_pos     = AVI_TellAbsolute( p_input );
326     if( p_pk->i_fourcc == AVIFOURCC_LIST )
327     {
328         p_pk->i_type = GetFOURCC( p_peek + 8 );
329     }
330     else
331     {
332         p_pk->i_type = 0;
333     }
334     
335     memcpy( p_pk->i_peek, p_peek + 8, 8 );
336
337     AVI_ParseStreamHeader( p_pk->i_fourcc, &p_pk->i_stream, &p_pk->i_cat );
338     return VLC_SUCCESS;
339 }
340
341 static int AVI_PacketNext( input_thread_t *p_input )
342 {
343     avi_packet_t    avi_ck;
344
345     if( AVI_PacketGetHeader( p_input, &avi_ck ) )
346     {
347         return VLC_EGENERIC;
348     }
349     if( avi_ck.i_fourcc == AVIFOURCC_LIST && avi_ck.i_type == AVIFOURCC_rec )
350     {
351         return AVI_SkipBytes( p_input, 12 );
352     }
353     else
354     {
355         return AVI_SkipBytes( p_input, __EVEN( avi_ck.i_size ) + 8 );
356     }
357 }
358 static int AVI_PacketRead( input_thread_t   *p_input,
359                            avi_packet_t     *p_pk,
360                            pes_packet_t     **pp_pes )
361 {
362     int i_size;
363     vlc_bool_t b_pad;
364
365     i_size = __EVEN( p_pk->i_size + 8 );
366     b_pad  = ( i_size != p_pk->i_size + 8 );
367     
368     if( input_ReadInPES( p_input, pp_pes, i_size ) != i_size )
369     {
370         return VLC_EGENERIC;
371     }
372     (*pp_pes)->p_first->p_payload_start += 8;
373     (*pp_pes)->i_pes_size -= 8;
374
375     if( b_pad )
376     {
377         (*pp_pes)->p_last->p_payload_end--;
378         (*pp_pes)->i_pes_size--;
379     }
380
381     return VLC_SUCCESS;
382 }
383
384 static int AVI_PacketSearch( input_thread_t *p_input )
385 {
386     demux_sys_t     *p_avi = p_input->p_demux_data;
387
388     avi_packet_t    avi_pk;
389     for( ;; )
390     {
391         if( AVI_SkipBytes( p_input, 1 ) )
392         {
393             return VLC_EGENERIC;
394         }
395         AVI_PacketGetHeader( p_input, &avi_pk );
396         if( avi_pk.i_stream < p_avi->i_streams &&
397             ( avi_pk.i_cat == AUDIO_ES || avi_pk.i_cat == VIDEO_ES ) )
398         {
399             return VLC_SUCCESS;
400         }
401         switch( avi_pk.i_fourcc )
402         {
403             case AVIFOURCC_JUNK:
404             case AVIFOURCC_LIST:
405             case AVIFOURCC_idx1:
406                 return VLC_SUCCESS;
407         }
408     }
409 }
410
411
412 static void __AVI_AddEntryIndex( avi_stream_t *p_info,
413                                  AVIIndexEntry_t *p_index)
414 {
415     if( p_info->p_index == NULL )
416     {
417         p_info->i_idxmax = 16384;
418         p_info->i_idxnb = 0;
419         if( !( p_info->p_index = calloc( p_info->i_idxmax, 
420                                   sizeof( AVIIndexEntry_t ) ) ) )
421         {
422             return;
423         }
424     }
425     if( p_info->i_idxnb >= p_info->i_idxmax )
426     {
427         p_info->i_idxmax += 16384;
428         if( !( p_info->p_index = realloc( (void*)p_info->p_index,
429                            p_info->i_idxmax * 
430                            sizeof( AVIIndexEntry_t ) ) ) )
431         {
432             return;
433         }
434     }
435     /* calculate cumulate length */
436     if( p_info->i_idxnb > 0 )
437     {
438         p_index->i_lengthtotal = 
439             p_info->p_index[p_info->i_idxnb - 1].i_length +
440                 p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal;
441     }
442     else
443     {
444         p_index->i_lengthtotal = 0;
445     }
446
447     p_info->p_index[p_info->i_idxnb] = *p_index;
448     p_info->i_idxnb++;
449
450 }
451
452 static void AVI_IndexAddEntry( demux_sys_t *p_avi, 
453                                int i_stream, 
454                                AVIIndexEntry_t *p_index)
455 {
456     __AVI_AddEntryIndex( p_avi->pp_info[i_stream],
457                          p_index );
458     if( p_avi->i_movi_lastchunk_pos < p_index->i_pos )
459     {
460         p_avi->i_movi_lastchunk_pos = p_index->i_pos;
461     }
462 }
463
464 static void AVI_IndexLoad( input_thread_t *p_input )
465 {
466     demux_sys_t *p_avi = p_input->p_demux_data;
467     
468     avi_chunk_list_t    *p_riff;
469     avi_chunk_list_t    *p_movi;
470     avi_chunk_idx1_t    *p_idx1;
471
472     int i_stream;
473     int i_index;
474     off_t   i_offset;
475     
476     p_riff = (avi_chunk_list_t*)AVI_ChunkFind( &p_avi->ck_root, 
477                                                AVIFOURCC_RIFF, 0);
478     
479     p_idx1 = (avi_chunk_idx1_t*)AVI_ChunkFind( p_riff, AVIFOURCC_idx1, 0);
480     p_movi = (avi_chunk_list_t*)AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
481
482     if( !p_idx1 )
483     {
484         msg_Warn( p_input, "cannot find idx1 chunk, no index defined" );
485         return;
486     }
487     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
488     {
489         p_avi->pp_info[i_stream]->i_idxnb  = 0;
490         p_avi->pp_info[i_stream]->i_idxmax = 0;
491         p_avi->pp_info[i_stream]->p_index  = NULL;
492     }
493     /* *** calculate offset *** */
494     if( p_idx1->i_entry_count > 0 && 
495         p_idx1->entry[0].i_pos < p_movi->i_chunk_pos )
496     {
497         i_offset = p_movi->i_chunk_pos + 8;
498     }
499     else
500     {
501         i_offset = 0;
502     }
503
504     for( i_index = 0; i_index < p_idx1->i_entry_count; i_index++ )
505     {
506         int i_cat;
507         
508         AVI_ParseStreamHeader( p_idx1->entry[i_index].i_fourcc,
509                                &i_stream,
510                                &i_cat );
511         if( i_stream < p_avi->i_streams &&
512             i_cat == p_avi->pp_info[i_stream]->i_cat )
513         {
514             AVIIndexEntry_t index;
515             index.i_id      = p_idx1->entry[i_index].i_fourcc;
516             index.i_flags   = 
517                 p_idx1->entry[i_index].i_flags&(~AVIIF_FIXKEYFRAME);
518             index.i_pos     = p_idx1->entry[i_index].i_pos + i_offset;
519             index.i_length  = p_idx1->entry[i_index].i_length;
520             AVI_IndexAddEntry( p_avi, i_stream, &index );
521         }
522     }
523     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
524     {
525         msg_Dbg( p_input, 
526                 "stream[%d] creating %d index entries", 
527                 i_stream,
528                 p_avi->pp_info[i_stream]->i_idxnb );
529     }
530     
531 }
532
533 static void AVI_IndexCreate( input_thread_t *p_input )
534 {
535     demux_sys_t *p_avi = p_input->p_demux_data;
536     
537     avi_chunk_list_t    *p_riff;
538     avi_chunk_list_t    *p_movi;
539
540     int i_stream;
541     off_t   i_movi_end;
542     
543     p_riff = (avi_chunk_list_t*)AVI_ChunkFind( &p_avi->ck_root, 
544                                                AVIFOURCC_RIFF, 0);
545     p_movi = (avi_chunk_list_t*)AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
546     
547     if( !p_movi )
548     {
549         msg_Err( p_input, "cannot find p_movi" );
550         return;
551     }
552
553     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
554     {
555         p_avi->pp_info[i_stream]->i_idxnb  = 0;
556         p_avi->pp_info[i_stream]->i_idxmax = 0;
557         p_avi->pp_info[i_stream]->p_index  = NULL;
558     }
559     i_movi_end = __MIN( p_movi->i_chunk_pos + p_movi->i_chunk_size,
560                         p_input->stream.p_selected_area->i_size );
561
562     AVI_SeekAbsolute( p_input, p_movi->i_chunk_pos + 12);
563     msg_Warn( p_input, "creating index from LIST-movi, will take time !" );
564     for( ;; )
565     {
566         avi_packet_t pk;
567         
568         if( AVI_PacketGetHeader( p_input, &pk ) )
569         {
570             break;
571         }
572         if( pk.i_stream < p_avi->i_streams &&
573             pk.i_cat == p_avi->pp_info[pk.i_stream]->i_cat )
574         {
575             AVIIndexEntry_t index;
576             index.i_id      = pk.i_fourcc;
577             index.i_flags   = 
578                AVI_GetKeyFlag(p_avi->pp_info[pk.i_stream]->i_codec, pk.i_peek);
579             index.i_pos     = pk.i_pos;
580             index.i_length  = pk.i_size;
581             AVI_IndexAddEntry( p_avi, pk.i_stream, &index );
582         }
583         else
584         {
585             switch( pk.i_fourcc )
586             {
587                 case AVIFOURCC_idx1:
588                     goto print_stat;
589                 case AVIFOURCC_rec:
590                 case AVIFOURCC_JUNK:
591                     break;
592                 default:
593                     msg_Warn( p_input, "need resync, probably broken avi" );
594                     if( AVI_PacketSearch( p_input ) )
595                     {
596                         msg_Warn( p_input, "lost sync, abord index creation" );
597                         goto print_stat;
598                     }
599             }
600         }
601         if( pk.i_pos + pk.i_size >= i_movi_end ||
602             AVI_PacketNext( p_input ) )
603         {
604             break;
605         }
606     }
607
608 print_stat:
609     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
610     {
611         msg_Dbg( p_input, 
612                 "stream[%d] creating %d index entries", 
613                 i_stream,
614                 p_avi->pp_info[i_stream]->i_idxnb );
615     }
616 }
617
618
619 /*****************************************************************************
620  * Stream management
621  *****************************************************************************/
622 static vlc_bool_t AVI_StreamStart ( input_thread_t *, demux_sys_t *, int );
623 static int  AVI_StreamSeek   ( input_thread_t *, demux_sys_t *, int, mtime_t );
624 static void AVI_StreamStop   ( input_thread_t *, demux_sys_t *, int );
625
626 static vlc_bool_t AVI_StreamStart( input_thread_t *p_input,  
627                                    demux_sys_t *p_avi, int i_stream )
628 {
629 #define p_stream    p_avi->pp_info[i_stream]
630     if( !p_stream->p_es )
631     {
632         msg_Warn( p_input, "stream[%d] unselectable", i_stream );
633         return VLC_FALSE;
634     }
635     if( p_stream->b_activated )
636     {
637         msg_Warn( p_input, "stream[%d] already selected", i_stream );
638         return VLC_TRUE;
639     }
640     
641     if( !p_stream->p_es->p_decoder_fifo )
642     {
643         vlc_mutex_lock( &p_input->stream.stream_lock );
644         input_SelectES( p_input, p_stream->p_es );
645         vlc_mutex_unlock( &p_input->stream.stream_lock );
646     }
647     p_stream->b_activated = p_stream->p_es->p_decoder_fifo ? VLC_TRUE
648                                                            : VLC_FALSE;
649     if( p_stream->b_activated && p_avi->b_seekable)
650     {
651         AVI_StreamSeek( p_input, p_avi, i_stream, p_avi->i_time );
652     }
653
654     return p_stream->b_activated;
655 #undef  p_stream
656 }
657
658 static void    AVI_StreamStop( input_thread_t *p_input,
659                                demux_sys_t *p_avi, int i_stream )
660 {
661 #define p_stream    p_avi->pp_info[i_stream]
662
663     if( !p_stream->b_activated )
664     {
665         msg_Warn( p_input, "stream[%d] already unselected", i_stream );
666         return;
667     }
668     
669     if( p_stream->p_es->p_decoder_fifo )
670     {
671         vlc_mutex_lock( &p_input->stream.stream_lock );
672         input_UnselectES( p_input, p_stream->p_es );
673         vlc_mutex_unlock( &p_input->stream.stream_lock );
674     }
675
676             
677     p_stream->b_activated = VLC_FALSE;
678
679 #undef  p_stream
680 }
681
682 /****************************************************************************
683  * AVI_MovieGetLength give max streams length in second
684  ****************************************************************************/
685 static mtime_t  AVI_MovieGetLength( input_thread_t *p_input, demux_sys_t *p_avi )
686 {
687     int i_stream;
688     mtime_t i_maxlength;
689     
690     i_maxlength = 0;
691     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
692     {
693 #define p_stream  p_avi->pp_info[i_stream]
694         mtime_t i_length;
695         /* fix length for each stream */
696         if( p_stream->i_idxnb < 1 || !p_stream->p_index )
697         {
698             continue;
699         }
700
701         if( p_stream->i_samplesize )
702         {
703             i_length = 
704                 (mtime_t)( p_stream->p_index[p_stream->i_idxnb-1].i_lengthtotal + 
705                            p_stream->p_index[p_stream->i_idxnb-1].i_length ) /
706                 (mtime_t)p_stream->i_scale /
707                 (mtime_t)p_stream->i_rate /
708                 (mtime_t)p_stream->i_samplesize;
709         }
710         else
711         {
712             i_length = (mtime_t)p_stream->i_idxnb *
713                        (mtime_t)p_stream->i_scale /
714                        (mtime_t)p_stream->i_rate;
715         }
716
717         msg_Dbg( p_input, 
718                  "stream[%d] length:"I64Fd" (based on index)",
719                  i_stream,
720                  i_length );
721         i_maxlength = __MAX( i_maxlength, i_length );
722 #undef p_stream                         
723     }
724
725     return i_maxlength;
726 }
727
728 /*****************************************************************************
729  * AVIEnd: frees unused data
730  *****************************************************************************/
731 static void __AVIEnd ( vlc_object_t * p_this )
732 {   
733     input_thread_t *    p_input = (input_thread_t *)p_this;
734     int i;
735     demux_sys_t *p_avi = p_input->p_demux_data  ; 
736     
737     if( p_avi->pp_info )
738     {
739         for( i = 0; i < p_avi->i_streams; i++ )
740         {
741             if( p_avi->pp_info[i] ) 
742             {
743                 if( p_avi->pp_info[i]->p_index )
744                 {
745                       free( p_avi->pp_info[i]->p_index );
746                 }
747                 free( p_avi->pp_info[i] ); 
748             }
749         }
750          free( p_avi->pp_info );
751     }
752 #ifdef __AVI_SUBTITLE__
753     if( p_avi->p_sub )
754     {
755         subtitle_Close( p_avi->p_sub );
756         p_avi->p_sub = NULL;
757     }
758 #endif
759     AVI_ChunkFreeRoot( p_input, &p_avi->ck_root );
760 }
761
762 /*****************************************************************************
763  * AVIInit: check file and initializes AVI structures
764  *****************************************************************************/
765 static int AVIInit( vlc_object_t * p_this )
766 {   
767     input_thread_t *    p_input = (input_thread_t *)p_this;
768     avi_chunk_t         ck_riff;
769     avi_chunk_list_t    *p_riff = (avi_chunk_list_t*)&ck_riff;
770     avi_chunk_list_t    *p_hdrl, *p_movi;
771 #if 0
772     avi_chunk_list_t    *p_INFO;
773     avi_chunk_strz_t    *p_name;
774 #endif
775     avi_chunk_avih_t    *p_avih;
776     demux_sys_t *p_avi;
777     es_descriptor_t *p_es = NULL; /* avoid warning */
778     int i;
779 #ifdef __AVI_SUBTITLE__
780     mtime_t i_microsecperframe = 0; // for some subtitle format
781 #endif
782     
783     vlc_bool_t b_stream_audio, b_stream_video; 
784
785     p_input->pf_demux = AVIDemux_Seekable;
786     if( AVI_TestFile( p_input ) )
787     {
788         msg_Warn( p_input, "avi module discarded (invalid headr)" );
789         return VLC_EGENERIC;
790     }
791
792     /* Initialize access plug-in structures. */
793     if( p_input->i_mtu == 0 )
794     {
795         /* Improve speed. */
796         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
797     }
798
799     if( !( p_input->p_demux_data = 
800                     p_avi = malloc( sizeof(demux_sys_t) ) ) )
801     {
802         msg_Err( p_input, "out of memory" );
803         return VLC_ENOMEM;
804     }
805     memset( p_avi, 0, sizeof( demux_sys_t ) );
806     p_avi->i_time = 0;
807     p_avi->i_pcr  = 0;
808     p_avi->b_seekable = ( ( p_input->stream.b_seekable )
809                         &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
810     p_avi->i_movi_lastchunk_pos = 0;
811
812     /* *** for unseekable stream, automaticaly use AVIDemux_interleaved *** */
813     if( !p_avi->b_seekable || config_GetInt( p_input, "avi-interleaved" ) )
814     {
815         p_input->pf_demux = AVIDemux_UnSeekable;
816     }
817     
818     if( AVI_ChunkReadRoot( p_input, &p_avi->ck_root, p_avi->b_seekable ) )
819     {
820         msg_Err( p_input, "avi module discarded (invalid file)" );
821         return VLC_EGENERIC;
822     }
823     AVI_ChunkDumpDebug( p_input, &p_avi->ck_root );
824
825
826     p_riff  = (avi_chunk_list_t*)AVI_ChunkFind( &p_avi->ck_root, 
827                                                 AVIFOURCC_RIFF, 0 );
828     p_hdrl  = (avi_chunk_list_t*)AVI_ChunkFind( p_riff,
829                                                 AVIFOURCC_hdrl, 0 );
830     p_movi  = (avi_chunk_list_t*)AVI_ChunkFind( p_riff, 
831                                                 AVIFOURCC_movi, 0 );
832 #if 0
833     p_INFO  = (avi_chunk_list_t*)AVI_ChunkFind( p_riff,
834                                                 AVIFOURCC_INFO, 0 );
835     p_name  = (avi_chunk_strz_t*)AVI_ChunkFind( p_INFO,
836                                                 AVIFOURCC_INAM, 0 );
837     if( p_name )
838     {
839         
840     }
841 #endif
842
843     if( !p_hdrl || !p_movi )
844     {
845         msg_Err( p_input, "avi module discarded (invalid file)" );
846         return VLC_EGENERIC;
847     }
848     
849     if( !( p_avih = (avi_chunk_avih_t*)AVI_ChunkFind( p_hdrl, 
850                                                       AVIFOURCC_avih, 0 ) ) )
851     {
852         msg_Err( p_input, "cannot find avih chunk" );
853         return VLC_EGENERIC;
854     }
855     p_avi->i_streams = AVI_ChunkCount( p_hdrl, AVIFOURCC_strl );
856     if( p_avih->i_streams != p_avi->i_streams )
857     {
858         msg_Warn( p_input, 
859                   "found %d stream but %d are declared",
860                   p_avi->i_streams,
861                   p_avih->i_streams );
862     }
863     if( p_avi->i_streams == 0 )
864     {
865         AVIEnd( p_input );
866         msg_Err( p_input, "no stream defined!" );
867         return VLC_EGENERIC;
868     }
869
870     /*  create one program */
871     vlc_mutex_lock( &p_input->stream.stream_lock );
872     if( input_InitStream( p_input, 0 ) == -1)
873     {
874         vlc_mutex_unlock( &p_input->stream.stream_lock );
875         AVIEnd( p_input );
876         msg_Err( p_input, "cannot init stream" );
877         return VLC_EGENERIC;
878     }
879     if( input_AddProgram( p_input, 0, 0) == NULL )
880     {
881         vlc_mutex_unlock( &p_input->stream.stream_lock );
882         AVIEnd( p_input );
883         msg_Err( p_input, "cannot add program" );
884         return VLC_EGENERIC;
885     }
886     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
887     vlc_mutex_unlock( &p_input->stream.stream_lock ); 
888     
889     /* print informations on streams */
890     msg_Dbg( p_input, "AVIH: %d stream, flags %s%s%s%s ", 
891              p_avi->i_streams,
892              p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
893              p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
894              p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
895              p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
896
897     /* now read info on each stream and create ES */
898     p_avi->pp_info = calloc( p_avi->i_streams, 
899                             sizeof( avi_stream_t* ) );
900     memset( p_avi->pp_info, 
901             0, 
902             sizeof( avi_stream_t* ) * p_avi->i_streams );
903
904     for( i = 0 ; i < p_avi->i_streams; i++ )
905     {
906         avi_chunk_list_t    *p_avi_strl;
907         avi_chunk_strh_t    *p_avi_strh;
908         avi_chunk_strf_auds_t    *p_avi_strf_auds;
909         avi_chunk_strf_vids_t    *p_avi_strf_vids;
910         int     i_init_size;
911         void    *p_init_data;
912 #define p_info  p_avi->pp_info[i]
913         p_info = malloc( sizeof(avi_stream_t ) );
914         memset( p_info, 0, sizeof( avi_stream_t ) );        
915     
916         p_avi_strl = (avi_chunk_list_t*)AVI_ChunkFind( p_hdrl, 
917                                                        AVIFOURCC_strl, i );
918         p_avi_strh = (avi_chunk_strh_t*)AVI_ChunkFind( p_avi_strl, 
919                                                        AVIFOURCC_strh, 0 );
920         p_avi_strf_auds = (avi_chunk_strf_auds_t*)
921             p_avi_strf_vids = (avi_chunk_strf_vids_t*)
922                 AVI_ChunkFind( p_avi_strl, AVIFOURCC_strf, 0 );
923
924         if( !p_avi_strl || !p_avi_strh || 
925                 ( !p_avi_strf_auds && !p_avi_strf_vids ) )
926         {
927             msg_Warn( p_input, "stream[%d] incomlete", i );
928             continue;
929         }
930         
931         /* *** Init p_info *** */
932         p_info->i_rate  = p_avi_strh->i_rate;
933         p_info->i_scale = p_avi_strh->i_scale;
934         p_info->i_samplesize = p_avi_strh->i_samplesize;
935
936         switch( p_avi_strh->i_type )
937         {
938             case( AVIFOURCC_auds ):
939                 p_info->i_cat = AUDIO_ES;
940                 p_info->i_fourcc = 
941                     AVI_FourccGetCodec( AUDIO_ES, 
942                                         p_avi_strf_auds->p_wf->wFormatTag );
943                 p_info->i_codec  = p_info->i_fourcc;
944                 i_init_size = p_avi_strf_auds->i_chunk_size;
945                 p_init_data = p_avi_strf_auds->p_wf;
946                 msg_Dbg( p_input, "stream[%d] audio(0x%x) %d channels %dHz %dbits",
947                         i,
948                         p_avi_strf_auds->p_wf->wFormatTag,
949                         p_avi_strf_auds->p_wf->nChannels,
950                         p_avi_strf_auds->p_wf->nSamplesPerSec,
951                         p_avi_strf_auds->p_wf->wBitsPerSample );
952                 break;
953                 
954             case( AVIFOURCC_vids ):
955                 p_info->i_cat = VIDEO_ES;
956                 /* XXX quick hack for playing ffmpeg video, I don't know 
957                     who is doing something wrong */
958                 p_info->i_samplesize = 0;
959                 p_info->i_fourcc = p_avi_strf_vids->p_bih->biCompression;
960                 p_info->i_codec = 
961                     AVI_FourccGetCodec( VIDEO_ES, p_info->i_fourcc );
962                 i_init_size = p_avi_strf_vids->i_chunk_size;
963                 p_init_data = p_avi_strf_vids->p_bih;
964                 msg_Dbg( p_input, "stream[%d] video(%4.4s) %dx%d %dbpp %ffps",
965                         i,
966                          (char*)&p_avi_strf_vids->p_bih->biCompression,
967                          p_avi_strf_vids->p_bih->biWidth,
968                          p_avi_strf_vids->p_bih->biHeight,
969                          p_avi_strf_vids->p_bih->biBitCount,
970                          (float)p_info->i_rate /
971                              (float)p_info->i_scale );
972 #ifdef __AVI_SUBTITLE__
973                 if( i_microsecperframe == 0 )
974                 {
975                     i_microsecperframe = (mtime_t)1000000 *
976                                          (mtime_t)p_info->i_scale /
977                                          (mtime_t)p_info->i_rate;
978                 }
979 #endif
980                 break;
981             default:
982                 msg_Err( p_input, "stream[%d] unknown type", i );
983                 p_info->i_cat = UNKNOWN_ES;
984                 i_init_size = 0;
985                 p_init_data = NULL;
986                 break;
987         }
988         p_info->b_activated = VLC_FALSE;
989         /* add one ES */
990         vlc_mutex_lock( &p_input->stream.stream_lock );
991         p_info->p_es =
992             p_es = input_AddES( p_input,
993                                 p_input->stream.p_selected_program, 1+i,
994                                 i_init_size );
995         vlc_mutex_unlock( &p_input->stream.stream_lock );
996         p_es->i_stream_id =i; /* XXX: i don't use it */ 
997         p_es->i_fourcc = p_info->i_fourcc;
998         p_es->i_cat = p_info->i_cat;
999
1000         /* We copy strf for decoder in p_es->p_demux_data */
1001         if( p_init_data )
1002         {
1003             memcpy( p_es->p_demux_data, 
1004                     p_init_data,
1005                     i_init_size );
1006         }
1007 #undef p_info           
1008     }
1009
1010 #ifdef __AVI_SUBTITLE__
1011     if( ( p_avi->p_sub = subtitle_New( p_input, NULL, i_microsecperframe ) ) )
1012     {
1013         subtitle_Select( p_avi->p_sub );
1014     }
1015 #endif
1016
1017     if( config_GetInt( p_input, "avi-index" ) )
1018     {
1019         if( p_avi->b_seekable )
1020         {
1021             AVI_IndexCreate( p_input );
1022         }
1023         else
1024         {
1025             msg_Warn( p_input, "cannot create index (unseekable stream)" );
1026             AVI_IndexLoad( p_input );
1027         }
1028     }
1029     else
1030     {
1031         AVI_IndexLoad( p_input );
1032     }
1033     
1034     /* *** movie length in sec *** */
1035 #if 0
1036     p_avi->i_length = (mtime_t)p_avih->i_totalframes * 
1037                       (mtime_t)p_avih->i_microsecperframe / 
1038                       (mtime_t)1000000;
1039 #endif
1040
1041     p_avi->i_length = AVI_MovieGetLength( p_input, p_avi );
1042     if( p_avi->i_length < (mtime_t)p_avih->i_totalframes *
1043                           (mtime_t)p_avih->i_microsecperframe /
1044                           (mtime_t)1000000 )
1045     {
1046         msg_Warn( p_input, "broken or missing index, 'seek' will be axproximative or will have strange behavour" );
1047     }
1048
1049     vlc_mutex_lock( &p_input->stream.stream_lock ); 
1050     if( p_avi->i_length )
1051     {
1052         p_input->stream.i_mux_rate = 
1053             p_input->stream.p_selected_area->i_size / 50 / p_avi->i_length;
1054     }
1055     else
1056     {
1057         p_input->stream.i_mux_rate = 0;
1058     }
1059     vlc_mutex_unlock( &p_input->stream.stream_lock ); 
1060
1061     b_stream_audio = VLC_FALSE;
1062     b_stream_video = VLC_FALSE;
1063     
1064     for( i = 0; i < p_avi->i_streams; i++ )
1065     {
1066 #define p_info  p_avi->pp_info[i]
1067         switch( p_info->p_es->i_cat )
1068         {
1069             case( VIDEO_ES ):
1070
1071                 if( !b_stream_video ) 
1072                 {
1073                     b_stream_video = AVI_StreamStart( p_input, p_avi, i );
1074                 }
1075                 break;
1076
1077             case( AUDIO_ES ):
1078                 if( !b_stream_audio ) 
1079                 {
1080                     b_stream_audio = AVI_StreamStart( p_input, p_avi, i );
1081                 }
1082                 break;
1083             default:
1084                 break;
1085         }
1086 #undef p_info    
1087     }
1088
1089     if( !b_stream_video ) 
1090     {
1091         msg_Warn( p_input, "no video stream found" );
1092     }
1093     if( !b_stream_audio )
1094     {
1095         msg_Warn( p_input, "no audio stream found!" );
1096     }
1097
1098     vlc_mutex_lock( &p_input->stream.stream_lock );
1099     p_input->stream.p_selected_program->b_is_ok = 1;
1100     vlc_mutex_unlock( &p_input->stream.stream_lock );
1101     
1102     if( p_avi->b_seekable )
1103     {
1104         AVI_ChunkGoto( p_input, p_movi );
1105     }
1106     else
1107     {
1108         // already at begining of p_movi
1109     }
1110     AVI_SkipBytes( p_input, 12 ); // enter in p_movi
1111
1112     p_avi->i_movi_begin = p_movi->i_chunk_pos;
1113     return VLC_SUCCESS;
1114 }
1115
1116
1117
1118
1119 /*****************************************************************************
1120  * Function to convert pts to chunk or byte
1121  *****************************************************************************/
1122
1123 static inline mtime_t AVI_PTSToChunk( avi_stream_t *p_info, 
1124                                         mtime_t i_pts )
1125 {
1126     return (mtime_t)((int64_t)i_pts *
1127                      (int64_t)p_info->i_rate /
1128                      (int64_t)p_info->i_scale /
1129                      (int64_t)1000000 );
1130 }
1131 static inline mtime_t AVI_PTSToByte( avi_stream_t *p_info,
1132                                        mtime_t i_pts )
1133 {
1134     return (mtime_t)((int64_t)i_pts * 
1135                      (int64_t)p_info->i_samplesize *
1136                      (int64_t)p_info->i_rate /
1137                      (int64_t)p_info->i_scale /
1138                      (int64_t)1000000 );
1139
1140 }
1141
1142 static mtime_t AVI_GetDPTS( avi_stream_t *p_stream, int i_count )
1143 {
1144     if( p_stream->i_samplesize )
1145     {
1146         return (mtime_t)( (int64_t)1000000 *
1147                    (int64_t)i_count *
1148                    (int64_t)p_stream->i_scale /
1149                    (int64_t)p_stream->i_rate /
1150                    (int64_t)p_stream->i_samplesize );
1151     }
1152     else
1153     {
1154         return (mtime_t)( (int64_t)1000000 *
1155                    (int64_t)i_count *
1156                    (int64_t)p_stream->i_scale /
1157                    (int64_t)p_stream->i_rate);
1158     }
1159
1160 }
1161
1162 static mtime_t AVI_GetPTS( avi_stream_t *p_info )
1163 {
1164     
1165     if( p_info->i_samplesize )
1166     {
1167         /* we need a valid entry we will emulate one */
1168         int i_len;
1169         if( p_info->i_idxposc == p_info->i_idxnb )
1170         {
1171             if( p_info->i_idxposc )
1172             {
1173                 /* use the last entry */
1174                 i_len = p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal
1175                             + p_info->p_index[p_info->i_idxnb - 1].i_length
1176                             + p_info->i_idxposb; /* should be 0 */
1177             }
1178             else
1179             {
1180                 i_len = p_info->i_idxposb; 
1181                 /* no valid entry use only offset*/
1182             }
1183         }
1184         else
1185         {
1186             i_len = p_info->p_index[p_info->i_idxposc].i_lengthtotal
1187                                 + p_info->i_idxposb;
1188         }
1189         return (mtime_t)( (int64_t)1000000 *
1190                   (int64_t)i_len *
1191                    (int64_t)p_info->i_scale /
1192                    (int64_t)p_info->i_rate /
1193                    (int64_t)p_info->i_samplesize );
1194     }
1195     else
1196     {
1197         /* even if p_info->i_idxposc isn't valid, there isn't any problem */
1198         return (mtime_t)( (int64_t)1000000 *
1199                    (int64_t)(p_info->i_idxposc ) *
1200                    (int64_t)p_info->i_scale /
1201                    (int64_t)p_info->i_rate);
1202     }
1203 }
1204
1205 static int AVI_StreamChunkFind( input_thread_t *p_input,
1206                                 int i_stream )
1207 {
1208     demux_sys_t *p_avi = p_input->p_demux_data;
1209     avi_packet_t avi_pk;
1210
1211     /* find first chunk of i_stream that isn't in index */
1212
1213     if( p_avi->i_movi_lastchunk_pos >= p_avi->i_movi_begin )
1214     {
1215         AVI_SeekAbsolute( p_input, p_avi->i_movi_lastchunk_pos );
1216         if( AVI_PacketNext( p_input ) )
1217         {
1218             return VLC_EGENERIC;
1219         }
1220     }
1221     else
1222     {
1223         AVI_SeekAbsolute( p_input, p_avi->i_movi_begin );
1224     }
1225
1226     for( ;; )
1227     {
1228
1229         if( AVI_PacketGetHeader( p_input, &avi_pk ) )
1230         {
1231             msg_Err( p_input, "cannot get packet header" );
1232             return VLC_EGENERIC;
1233         }
1234         if( avi_pk.i_stream >= p_avi->i_streams ||
1235             ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
1236         {
1237             switch( avi_pk.i_fourcc )
1238             {
1239                 case AVIFOURCC_LIST:
1240                     AVI_SkipBytes( p_input, 12 );
1241                     break;
1242                 default:
1243                     if( AVI_PacketNext( p_input ) )
1244                     {
1245                         return VLC_EGENERIC;
1246                     }
1247                     break;
1248             }
1249         }
1250         else
1251         {
1252             /* add this chunk to the index */
1253             AVIIndexEntry_t index;
1254             
1255             index.i_id = avi_pk.i_fourcc;
1256             index.i_flags = 
1257                AVI_GetKeyFlag(p_avi->pp_info[avi_pk.i_stream]->i_codec,
1258                               avi_pk.i_peek);
1259             index.i_pos = avi_pk.i_pos;
1260             index.i_length = avi_pk.i_size;
1261             AVI_IndexAddEntry( p_avi, avi_pk.i_stream, &index );
1262
1263             if( avi_pk.i_stream == i_stream  )
1264             {
1265                 return VLC_SUCCESS;
1266             }
1267             
1268             if( AVI_PacketNext( p_input ) )
1269             {
1270                 return VLC_EGENERIC;
1271             }
1272         }
1273     }
1274 }
1275
1276
1277 /* be sure that i_ck will be a valid index entry */
1278 static int AVI_SetStreamChunk( input_thread_t    *p_input,
1279                                int i_stream,
1280                                int i_ck )
1281 {
1282     demux_sys_t *p_avi = p_input->p_demux_data;
1283     avi_stream_t *p_stream = p_avi->pp_info[i_stream];
1284     
1285     p_stream->i_idxposc = i_ck;
1286     p_stream->i_idxposb = 0;
1287
1288     if(  i_ck >= p_stream->i_idxnb )
1289     {
1290         p_stream->i_idxposc = p_stream->i_idxnb - 1;
1291         do
1292         {
1293             p_stream->i_idxposc++;
1294             if( AVI_StreamChunkFind( p_input, i_stream ) )
1295             {
1296                 return VLC_EGENERIC;
1297             }
1298
1299         } while( p_stream->i_idxposc < i_ck );
1300     }
1301
1302     return VLC_SUCCESS;
1303 }
1304
1305
1306 /* XXX FIXME up to now, we assume that all chunk are one after one */
1307 static int AVI_SetStreamBytes( input_thread_t    *p_input, 
1308                                int i_stream,
1309                                off_t   i_byte )
1310 {
1311     demux_sys_t *p_avi = p_input->p_demux_data;
1312     avi_stream_t *p_stream = p_avi->pp_info[i_stream];
1313
1314     if( ( p_stream->i_idxnb > 0 )
1315         &&( i_byte < p_stream->p_index[p_stream->i_idxnb - 1].i_lengthtotal + 
1316                 p_stream->p_index[p_stream->i_idxnb - 1].i_length ) )
1317     {
1318         /* index is valid to find the ck */
1319         /* uses dichototmie to be fast enougth */
1320         int i_idxposc = __MIN( p_stream->i_idxposc, p_stream->i_idxnb - 1 );
1321         int i_idxmax  = p_stream->i_idxnb;
1322         int i_idxmin  = 0;
1323         for( ;; )
1324         {
1325             if( p_stream->p_index[i_idxposc].i_lengthtotal > i_byte )
1326             {
1327                 i_idxmax  = i_idxposc ;
1328                 i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
1329             }
1330             else
1331             {
1332                 if( p_stream->p_index[i_idxposc].i_lengthtotal + 
1333                         p_stream->p_index[i_idxposc].i_length <= i_byte)
1334                 {
1335                     i_idxmin  = i_idxposc ;
1336                     i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
1337                 }
1338                 else
1339                 {
1340                     p_stream->i_idxposc = i_idxposc;
1341                     p_stream->i_idxposb = i_byte - 
1342                             p_stream->p_index[i_idxposc].i_lengthtotal;
1343                     return VLC_SUCCESS;
1344                 }
1345             }
1346         }
1347         
1348     }
1349     else
1350     {
1351         p_stream->i_idxposc = p_stream->i_idxnb - 1;
1352         p_stream->i_idxposb = 0;
1353         do
1354         {
1355             p_stream->i_idxposc++;
1356             if( AVI_StreamChunkFind( p_input, i_stream ) )
1357             {
1358                 return VLC_EGENERIC;
1359             }
1360
1361         } while( p_stream->p_index[p_stream->i_idxposc].i_lengthtotal +
1362                     p_stream->p_index[p_stream->i_idxposc].i_length <= i_byte );
1363
1364         p_stream->i_idxposb = i_byte -
1365                        p_stream->p_index[p_stream->i_idxposc].i_lengthtotal;
1366         return VLC_SUCCESS;
1367     }
1368 }
1369
1370 static int AVI_StreamSeek( input_thread_t *p_input,
1371                            demux_sys_t  *p_avi,
1372                            int i_stream, 
1373                            mtime_t i_date )
1374 {
1375 #define p_stream    p_avi->pp_info[i_stream]
1376     mtime_t i_oldpts;
1377     
1378     i_oldpts = AVI_GetPTS( p_stream );
1379
1380     if( !p_stream->i_samplesize )
1381     {
1382         if( AVI_SetStreamChunk( p_input,
1383                                 i_stream, 
1384                                 AVI_PTSToChunk( p_stream, i_date ) ) )
1385         {
1386             return VLC_EGENERIC;
1387         }
1388                 
1389         /* search key frame */
1390         msg_Dbg( p_input, 
1391                  "old:"I64Fd" %s new "I64Fd,
1392                  i_oldpts, 
1393                  i_oldpts > i_date ? ">" : "<",
1394                  i_date );
1395
1396         if( i_date < i_oldpts )
1397         {
1398             while( p_stream->i_idxposc > 0 && 
1399                !( p_stream->p_index[p_stream->i_idxposc].i_flags & 
1400                                                             AVIIF_KEYFRAME ) )
1401             {
1402                 if( AVI_SetStreamChunk( p_input,
1403                                         i_stream,
1404                                         p_stream->i_idxposc - 1 ) )
1405                 {
1406                     return VLC_EGENERIC;
1407                 }
1408             }
1409         }
1410         else
1411         {
1412             while( p_stream->i_idxposc < p_stream->i_idxnb &&
1413                     !( p_stream->p_index[p_stream->i_idxposc].i_flags &
1414                                                             AVIIF_KEYFRAME ) )
1415             {
1416                 if( AVI_SetStreamChunk( p_input, 
1417                                         i_stream, 
1418                                         p_stream->i_idxposc + 1 ) )
1419                 {
1420                     return VLC_EGENERIC;
1421                 }
1422             }
1423         }
1424     }
1425     else
1426     {
1427         if( AVI_SetStreamBytes( p_input,
1428                                 i_stream,
1429                                 AVI_PTSToByte( p_stream, i_date ) ) )
1430         {
1431             return VLC_EGENERIC;
1432         }
1433     }
1434     return VLC_SUCCESS;
1435 #undef p_stream
1436 }
1437
1438 /*****************************************************************************
1439  * AVISeek: goto to i_date or i_percent
1440  *****************************************************************************
1441  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1442  *****************************************************************************/
1443 static int    AVISeek   ( input_thread_t *p_input, 
1444                           mtime_t i_date, int i_percent )
1445 {
1446
1447     demux_sys_t *p_avi = p_input->p_demux_data;
1448     int         i_stream;
1449     msg_Dbg( p_input, 
1450              "seek requested: "I64Fd" secondes %d%%", 
1451              i_date / 1000000,
1452              i_percent );
1453
1454     if( p_avi->b_seekable )
1455     {
1456         if( !p_avi->i_length )
1457         {
1458             avi_stream_t *p_stream;
1459             uint64_t i_pos;
1460
1461             /* use i_percent to create a true i_date */
1462             msg_Warn( p_input, 
1463                       "mmh, seeking without index at %d%%"
1464                       " work only for interleaved file", i_percent );
1465
1466             if( i_percent >= 100 )
1467             {
1468                 msg_Err( p_input, "cannot seek so far !" );
1469                 return( -1 );
1470             }
1471             i_percent = __MAX( i_percent, 0 );
1472             
1473             /* try to find chunk that is at i_percent or the file */
1474             i_pos = __MAX( i_percent * 
1475                            p_input->stream.p_selected_area->i_size / 100,
1476                            p_avi->i_movi_begin );
1477             /* search first selected stream */
1478             for( i_stream = 0, p_stream = NULL; 
1479                         i_stream < p_avi->i_streams; i_stream++ )
1480             {
1481                 p_stream = p_avi->pp_info[i_stream];
1482                 if( p_stream->b_activated )
1483                 {
1484                     break;
1485                 }
1486             }
1487             if( !p_stream || !p_stream->b_activated )
1488             {
1489                 msg_Err( p_input, "cannot find any selected stream" );
1490                 return( -1 );
1491             }
1492             
1493             /* be sure that the index exit */
1494             if( AVI_SetStreamChunk( p_input, 
1495                                     i_stream,
1496                                     0 ) )
1497             {
1498                 msg_Err( p_input, "cannot seek" );
1499                 return( -1 );
1500             }
1501            
1502             while( i_pos >= p_stream->p_index[p_stream->i_idxposc].i_pos +
1503                p_stream->p_index[p_stream->i_idxposc].i_length + 8 )
1504             {
1505                 /* search after i_idxposc */
1506                 if( AVI_SetStreamChunk( p_input, 
1507                                         i_stream, p_stream->i_idxposc + 1 ) )
1508                 {
1509                     msg_Err( p_input, "cannot seek" );
1510                     return( -1 );
1511                 }
1512             }
1513             i_date = AVI_GetPTS( p_stream );
1514             /* TODO better support for i_samplesize != 0 */
1515             msg_Dbg( p_input, "estimate date "I64Fd, i_date );
1516         }
1517
1518 #define p_stream    p_avi->pp_info[i_stream]
1519         p_avi->i_time = 0;
1520         /* seek for chunk based streams */
1521         for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
1522         {
1523             if( p_stream->b_activated && !p_stream->i_samplesize )
1524 //            if( p_stream->b_activated )
1525             {
1526                 AVI_StreamSeek( p_input, p_avi, i_stream, i_date );
1527                 p_avi->i_time = __MAX( AVI_GetPTS( p_stream ), 
1528                                         p_avi->i_time );
1529             }
1530         }
1531 #if 1
1532         if( p_avi->i_time )
1533         {
1534             i_date = p_avi->i_time;
1535         }
1536         /* seek for bytes based streams */
1537         for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
1538         {
1539             if( p_stream->b_activated && p_stream->i_samplesize )
1540             {
1541                 AVI_StreamSeek( p_input, p_avi, i_stream, i_date );
1542 //                p_avi->i_time = __MAX( AVI_GetPTS( p_stream ), p_avi->i_time );
1543             }
1544         }
1545         msg_Dbg( p_input, "seek: "I64Fd" secondes", p_avi->i_time /1000000 );
1546         /* set true movie time */
1547 #endif
1548         if( !p_avi->i_time )
1549         {
1550             p_avi->i_time = i_date;
1551         }
1552 #undef p_stream
1553         return( 1 );
1554     }
1555     else
1556     {
1557         msg_Err( p_input, "shouldn't yet be executed" );
1558         return( -1 );
1559     }
1560 }
1561
1562 /*****************************************************************************
1563  * AVIDemux_Seekable: reads and demuxes data packets for stream seekable
1564  *****************************************************************************
1565  * AVIDemux: reads and demuxes data packets
1566  *****************************************************************************
1567  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1568  *****************************************************************************/
1569 typedef struct avi_stream_toread_s
1570
1571     vlc_bool_t b_ok;
1572
1573     int i_toread;
1574     
1575     off_t i_posf; // where we will read : 
1576                   // if i_idxposb == 0 : begining of chunk (+8 to acces data)
1577                   // else : point on data directly
1578 } avi_stream_toread_t;
1579
1580 static int AVIDemux_Seekable( input_thread_t *p_input )
1581 {
1582     int i_stream;
1583     vlc_bool_t b_stream;
1584
1585     // cannot be more than 100 stream (dcXX or wbXX)
1586     avi_stream_toread_t toread[100]; 
1587
1588     demux_sys_t *p_avi = p_input->p_demux_data;
1589
1590     /* detect new selected/unselected streams */
1591     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
1592     {
1593 #define p_stream    p_avi->pp_info[i_stream]
1594         if( p_stream->p_es )
1595         {
1596             if( p_stream->p_es->p_decoder_fifo &&
1597                 !p_stream->b_activated )
1598             {
1599                 AVI_StreamStart( p_input, p_avi, i_stream );
1600             }
1601             else
1602             if( !p_stream->p_es->p_decoder_fifo &&
1603                 p_stream->b_activated )
1604             {
1605                 AVI_StreamStop( p_input, p_avi, i_stream );
1606             }
1607         }       
1608 #undef  p_stream
1609     }
1610
1611     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
1612     {
1613         mtime_t i_date;
1614         int i_percent;
1615         /* first wait for empty buffer, arbitrary time FIXME */
1616 //        msleep( DEFAULT_PTS_DELAY );
1617
1618         i_date = (mtime_t)1000000 *
1619                  (mtime_t)p_avi->i_length *
1620                  (mtime_t)AVI_TellAbsolute( p_input ) /
1621                  (mtime_t)p_input->stream.p_selected_area->i_size;
1622         i_percent = 100 * AVI_TellAbsolute( p_input ) / 
1623                         p_input->stream.p_selected_area->i_size;
1624
1625 //        input_ClockInit( p_input->stream.p_selected_program );
1626         AVISeek( p_input, i_date, i_percent);
1627
1628 #ifdef __AVI_SUBTITLE__
1629         if( p_avi->p_sub )
1630         {
1631             subtitle_Seek( p_avi->p_sub, p_avi->i_time );
1632         }
1633 #endif
1634     }
1635
1636     
1637     /* wait for the good time */
1638
1639     p_avi->i_pcr = p_avi->i_time * 9 / 100;
1640
1641     input_ClockManageRef( p_input,
1642                           p_input->stream.p_selected_program,
1643                           p_avi->i_pcr ); 
1644
1645
1646     p_avi->i_time += 100*1000;  /* read 100ms */
1647
1648 #ifdef __AVI_SUBTITLE__
1649     if( p_avi->p_sub )
1650     {
1651         subtitle_Demux( p_avi->p_sub, p_avi->i_time );
1652     }
1653 #endif
1654     /* init toread */
1655     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
1656     {
1657 #define p_stream    p_avi->pp_info[i_stream]
1658         mtime_t i_dpts;
1659
1660         toread[i_stream].b_ok = p_stream->b_activated;
1661
1662         if( p_stream->i_idxposc < p_stream->i_idxnb )
1663         {
1664             toread[i_stream].i_posf = 
1665                 p_stream->p_index[p_stream->i_idxposc].i_pos;
1666            if( p_stream->i_idxposb > 0 )
1667            {
1668                 toread[i_stream].i_posf += 8 + p_stream->i_idxposb;
1669            }
1670         }
1671         else
1672         { 
1673             toread[i_stream].i_posf = -1;
1674         }
1675
1676         i_dpts = p_avi->i_time - AVI_GetPTS( p_stream  );
1677
1678         if( p_stream->i_samplesize )
1679         {
1680             toread[i_stream].i_toread = AVI_PTSToByte( p_stream, 
1681                                                        __ABS( i_dpts ) );
1682         }
1683         else
1684         {
1685             toread[i_stream].i_toread = AVI_PTSToChunk( p_stream,
1686                                                         __ABS( i_dpts ) );
1687         }
1688         
1689         if( i_dpts < 0 )
1690         {
1691             toread[i_stream].i_toread *= -1;
1692         }
1693 #undef  p_stream
1694     }
1695     
1696     b_stream = VLC_FALSE;
1697     
1698     for( ;; )
1699     {
1700 #define p_stream    p_avi->pp_info[i_stream]
1701         vlc_bool_t       b_done;
1702         pes_packet_t    *p_pes;
1703         off_t i_pos;
1704         int i;
1705         int i_size;
1706         
1707         /* search for first chunk to be read */
1708         for( i = 0, b_done = VLC_TRUE, i_pos = -1; i < p_avi->i_streams; i++ )
1709         {
1710             if( !toread[i].b_ok ||
1711                 AVI_GetDPTS( p_avi->pp_info[i],
1712                              toread[i].i_toread ) <= -25 * 1000 )
1713             {
1714                 continue;
1715             }
1716
1717             if( toread[i].i_toread > 0 )
1718             {
1719                 b_done = VLC_FALSE; // not yet finished
1720             }
1721
1722             if( toread[i].i_posf > 0 )
1723             {
1724                 if( i_pos == -1 || i_pos > toread[i_stream].i_posf )
1725                 {
1726                     i_stream = i;
1727                     i_pos = toread[i].i_posf;
1728                 }
1729             }
1730         }
1731
1732         if( b_done )
1733         {
1734 //            return( b_stream ? 1 : 0 );
1735             return( 1 );
1736         }
1737         
1738         if( i_pos == -1 )
1739         {
1740             /* no valid index, we will parse directly the stream */
1741             if( p_avi->i_movi_lastchunk_pos >= p_avi->i_movi_begin )
1742             {
1743                 AVI_SeekAbsolute( p_input, p_avi->i_movi_lastchunk_pos );
1744                 if( AVI_PacketNext( p_input ) )
1745                 {
1746                     return( 0 );
1747                 }
1748             }
1749             else
1750             {
1751                 AVI_SeekAbsolute( p_input, p_avi->i_movi_begin );
1752             }
1753
1754             for( ;; )
1755             {
1756                 avi_packet_t avi_pk;
1757
1758                 if( AVI_PacketGetHeader( p_input, &avi_pk ) )
1759                 {
1760                     msg_Err( p_input, "cannot get packet header" );
1761                     return( 0 );
1762                 }
1763                 if( avi_pk.i_stream >= p_avi->i_streams ||
1764                     ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
1765                 {
1766                     switch( avi_pk.i_fourcc )
1767                     {
1768                         case AVIFOURCC_LIST:
1769                             AVI_SkipBytes( p_input, 12 );
1770                             break;
1771                         default:
1772                             if( AVI_PacketNext( p_input ) )
1773                             {
1774                                 msg_Err( p_input, "cannot skip packet" );
1775                                 return( 0 );
1776                             }
1777                             break;
1778                     }
1779                     continue;
1780                 }
1781                 else
1782                 {
1783                     /* add this chunk to the index */
1784                     AVIIndexEntry_t index;
1785                     
1786                     index.i_id = avi_pk.i_fourcc;
1787                     index.i_flags = 
1788                        AVI_GetKeyFlag(p_avi->pp_info[avi_pk.i_stream]->i_codec,
1789                                       avi_pk.i_peek);
1790                     index.i_pos = avi_pk.i_pos;
1791                     index.i_length = avi_pk.i_size;
1792                     AVI_IndexAddEntry( p_avi, avi_pk.i_stream, &index );
1793
1794                     i_stream = avi_pk.i_stream;
1795                     /* do we will read this data ? */
1796                     if( AVI_GetDPTS( p_stream,
1797                              toread[i_stream].i_toread ) > -25 * 1000 )
1798                     {
1799                         break;
1800                     }
1801                     else
1802                     {
1803                         if( AVI_PacketNext( p_input ) )
1804                         {
1805                             msg_Err( p_input, "cannot skip packet" );
1806                             return( 0 );
1807                         }
1808                     }
1809                 }
1810             }
1811             
1812         }
1813         else
1814         {
1815             AVI_SeekAbsolute( p_input, i_pos );
1816         }
1817
1818         /* read thoses data */
1819         if( p_stream->i_samplesize )
1820         {
1821             i_size = __MIN( p_stream->p_index[p_stream->i_idxposc].i_length - 
1822                                 p_stream->i_idxposb,
1823                                 100 * 1024 ); // 10Ko max
1824 //                            toread[i_stream].i_toread );
1825         }
1826         else
1827         {
1828             i_size = p_stream->p_index[p_stream->i_idxposc].i_length;
1829         }
1830
1831         if( p_stream->i_idxposb == 0 )
1832         {
1833             i_size += 8; // need to read and skip header
1834         }
1835
1836         if( input_ReadInPES( p_input, &p_pes, __EVEN( i_size ) ) < 0 )
1837         {
1838             msg_Err( p_input, "failled reading data" );
1839             toread[i_stream].b_ok = VLC_FALSE;
1840             continue;
1841         }
1842
1843         if( i_size % 2 )    // read was padded on word boundary
1844         {
1845             p_pes->p_last->p_payload_end--;
1846             p_pes->i_pes_size--;
1847         }
1848         // skip header
1849         if( p_stream->i_idxposb == 0 )
1850         {
1851             p_pes->p_first->p_payload_start += 8;
1852             p_pes->i_pes_size -= 8;
1853         }
1854
1855         p_pes->i_pts = AVI_GetPTS( p_stream );
1856        
1857         /* read data */
1858         if( p_stream->i_samplesize )
1859         {
1860             if( p_stream->i_idxposb == 0 )
1861             {
1862                 i_size -= 8;
1863             }
1864             toread[i_stream].i_toread -= i_size;
1865             p_stream->i_idxposb += i_size;
1866             if( p_stream->i_idxposb >= 
1867                     p_stream->p_index[p_stream->i_idxposc].i_length )
1868             {
1869                 p_stream->i_idxposb = 0;
1870                 p_stream->i_idxposc++;
1871             }
1872         }
1873         else
1874         {
1875             toread[i_stream].i_toread--;
1876             p_stream->i_idxposc++;
1877         }
1878
1879         if( p_stream->i_idxposc < p_stream->i_idxnb)             
1880         {
1881             toread[i_stream].i_posf = 
1882                 p_stream->p_index[p_stream->i_idxposc].i_pos;
1883             if( p_stream->i_idxposb > 0 )
1884             {
1885                 toread[i_stream].i_posf += 8 + p_stream->i_idxposb;
1886             }
1887             
1888         }
1889         else
1890         {
1891             toread[i_stream].i_posf = -1;
1892         }
1893
1894         b_stream = VLC_TRUE; // at least one read succeed
1895         
1896         if( p_stream->p_es && p_stream->p_es->p_decoder_fifo )
1897         {
1898             p_pes->i_dts =
1899                 p_pes->i_pts = 
1900                     input_ClockGetTS( p_input,
1901                                       p_input->stream.p_selected_program,
1902                                       p_pes->i_pts * 9/100);
1903             
1904             input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
1905         }
1906         else
1907         {
1908             input_DeletePES( p_input->p_method_data, p_pes );
1909         }
1910     }
1911 }
1912
1913
1914 /*****************************************************************************
1915  * AVIDemux_UnSeekable: reads and demuxes data packets for unseekable file
1916  *****************************************************************************
1917  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1918  *****************************************************************************/
1919 static int AVIDemux_UnSeekable( input_thread_t *p_input )
1920 {
1921     demux_sys_t     *p_avi = p_input->p_demux_data;
1922     avi_stream_t *p_stream_master;
1923     vlc_bool_t b_audio;
1924     int     i_stream;
1925     int     i_packet;
1926
1927     /* *** send audio data to decoder only if rate == DEFAULT_RATE *** */
1928     vlc_mutex_lock( &p_input->stream.stream_lock );
1929     b_audio = p_input->stream.control.i_rate == DEFAULT_RATE;
1930     vlc_mutex_unlock( &p_input->stream.stream_lock );    
1931
1932     input_ClockManageRef( p_input,
1933                           p_input->stream.p_selected_program,
1934                           p_avi->i_pcr );
1935     /* *** find master stream for data packet skipping algo *** */
1936     /* *** -> first video, if any, or first audio ES *** */
1937     for( i_stream = 0, p_stream_master = NULL; 
1938             i_stream < p_avi->i_streams; i_stream++ )
1939     {
1940 #define p_stream    p_avi->pp_info[i_stream]
1941         if( p_stream->p_es &&
1942             p_stream->p_es->p_decoder_fifo )
1943         {
1944             if( p_stream->i_cat == VIDEO_ES )
1945             {
1946                 p_stream_master = p_stream;
1947                 break;
1948             }
1949             if( p_stream->i_cat == AUDIO_ES && !p_stream_master )
1950             {
1951                 p_stream_master = p_stream;
1952             }
1953         }
1954 #undef p_stream
1955     }
1956     if( !p_stream_master )
1957     {
1958         msg_Err( p_input, "no more stream selected" );
1959         return( 0 );
1960     }
1961
1962     p_avi->i_pcr = AVI_GetPTS( p_stream_master ) * 9 / 100;
1963     
1964     for( i_packet = 0; i_packet < 10; i_packet++)
1965     {
1966 #define p_stream    p_avi->pp_info[avi_pk.i_stream]
1967
1968         avi_packet_t    avi_pk;
1969
1970         if( AVI_PacketGetHeader( p_input, &avi_pk ) )
1971         {
1972             return( 0 );
1973         }
1974 //        AVI_ParseStreamHeader( avi_pk.i_fourcc, &i_stream, &i_cat );
1975
1976         if( avi_pk.i_stream >= p_avi->i_streams ||
1977             ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
1978         {
1979             /* we haven't found an audio or video packet:
1980              *  - we have seek, found first next packet
1981              *  - others packets could be found, skip them
1982              */
1983             switch( avi_pk.i_fourcc )
1984             {
1985                 case AVIFOURCC_JUNK:
1986                 case AVIFOURCC_LIST:
1987                     return( !AVI_PacketNext( p_input ) ? 1 : 0 );
1988                 case AVIFOURCC_idx1:
1989                     return( 0 );    // eof
1990                 default:
1991                     msg_Warn( p_input, 
1992                               "seems to have lost position, resync" );
1993                     if( AVI_PacketSearch( p_input ) )
1994                     {
1995                         msg_Err( p_input, "resync failed" );
1996                         return( -1 );
1997                     }
1998             }
1999         }
2000         else
2001         {  
2002             /* do will send this packet to decoder ? */
2003             if( ( !b_audio && avi_pk.i_cat == AUDIO_ES )||
2004                 !p_stream->p_es ||
2005                 !p_stream->p_es->p_decoder_fifo )
2006             {
2007                 if( AVI_PacketNext( p_input ) )
2008                 {
2009                     return( 0 );
2010                 }
2011             }
2012             else
2013             {
2014                 /* it's a selected stream, check for time */
2015                 if( __ABS( AVI_GetPTS( p_stream ) - 
2016                             AVI_GetPTS( p_stream_master ) )< 600*1000 )
2017                 {
2018                     /* load it and send to decoder */
2019                     pes_packet_t    *p_pes;
2020                     if( AVI_PacketRead( p_input, &avi_pk, &p_pes ) || !p_pes)
2021                     {
2022                         return( -1 );
2023                     }
2024                     p_pes->i_pts = 
2025                         input_ClockGetTS( p_input, 
2026                                           p_input->stream.p_selected_program, 
2027                                           AVI_GetPTS( p_stream ) * 9/100);
2028                     input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
2029                 }
2030                 else
2031                 {
2032                     if( AVI_PacketNext( p_input ) )
2033                     {
2034                         return( 0 );
2035                     }
2036                 }
2037             }
2038
2039             /* *** update stream time position *** */
2040             if( p_stream->i_samplesize )
2041             {
2042                 p_stream->i_idxposb += avi_pk.i_size;
2043             }
2044             else
2045             {
2046                 p_stream->i_idxposc++;
2047             }
2048
2049         }
2050
2051 #undef p_stream     
2052     }
2053
2054     return( 1 );
2055 }
2056