]> git.sesse.net Git - vlc/blob - modules/demux/avi/avi.c
* all: changed some msg_Err into msg_Warn.
[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.27 2003/01/20 13:01:53 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                             size_t 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, 2048 ) );
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( unsigned 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     size_t 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 ) != (ssize_t)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     unsigned int i_stream;
473     unsigned 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         unsigned 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     unsigned 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( (off_t)(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 static int  AVI_StreamStopFinishedStreams( input_thread_t *, demux_sys_t * );
626
627 static vlc_bool_t AVI_StreamStart( input_thread_t *p_input,
628                                    demux_sys_t *p_avi, int i_stream )
629 {
630 #define p_stream    p_avi->pp_info[i_stream]
631     if( !p_stream->p_es )
632     {
633         msg_Warn( p_input, "stream[%d] unselectable", i_stream );
634         return VLC_FALSE;
635     }
636     if( p_stream->b_activated )
637     {
638         msg_Warn( p_input, "stream[%d] already selected", i_stream );
639         return VLC_TRUE;
640     }
641
642     if( !p_stream->p_es->p_decoder_fifo )
643     {
644         vlc_mutex_lock( &p_input->stream.stream_lock );
645         input_SelectES( p_input, p_stream->p_es );
646         vlc_mutex_unlock( &p_input->stream.stream_lock );
647     }
648     p_stream->b_activated = p_stream->p_es->p_decoder_fifo ? VLC_TRUE
649                                                            : VLC_FALSE;
650     if( p_stream->b_activated && p_avi->b_seekable)
651     {
652         AVI_StreamSeek( p_input, p_avi, i_stream, p_avi->i_time );
653     }
654
655     return p_stream->b_activated;
656 #undef  p_stream
657 }
658
659 static void    AVI_StreamStop( input_thread_t *p_input,
660                                demux_sys_t *p_avi, int i_stream )
661 {
662 #define p_stream    p_avi->pp_info[i_stream]
663
664     if( !p_stream->b_activated )
665     {
666         msg_Warn( p_input, "stream[%d] already unselected", i_stream );
667         return;
668     }
669
670     if( p_stream->p_es->p_decoder_fifo )
671     {
672         vlc_mutex_lock( &p_input->stream.stream_lock );
673         input_UnselectES( p_input, p_stream->p_es );
674         vlc_mutex_unlock( &p_input->stream.stream_lock );
675     }
676
677
678     p_stream->b_activated = VLC_FALSE;
679
680 #undef  p_stream
681 }
682
683 static int AVI_StreamStopFinishedStreams( input_thread_t *p_input,
684                                            demux_sys_t *p_avi )
685 {
686     int i_stream;
687     int b_end;
688
689     for( i_stream = 0,b_end = VLC_TRUE;
690             i_stream < p_avi->i_streams; i_stream++ )
691     {
692 #define p_stream    p_avi->pp_info[i_stream]
693         if( p_stream->i_idxposc >= p_stream->i_idxnb )
694         {
695             AVI_StreamStop( p_input, p_avi, i_stream );
696         }
697         else
698         {
699             b_end = VLC_FALSE;
700         }
701 #undef  p_stream
702     }
703     return( b_end );
704 }
705 /****************************************************************************
706  * AVI_MovieGetLength give max streams length in second
707  ****************************************************************************/
708 static mtime_t  AVI_MovieGetLength( input_thread_t *p_input, demux_sys_t *p_avi )
709 {
710     unsigned int i_stream;
711     mtime_t i_maxlength;
712
713     i_maxlength = 0;
714     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
715     {
716 #define p_stream  p_avi->pp_info[i_stream]
717         mtime_t i_length;
718         /* fix length for each stream */
719         if( p_stream->i_idxnb < 1 || !p_stream->p_index )
720         {
721             continue;
722         }
723
724         if( p_stream->i_samplesize )
725         {
726             i_length =
727                 (mtime_t)( p_stream->p_index[p_stream->i_idxnb-1].i_lengthtotal +
728                            p_stream->p_index[p_stream->i_idxnb-1].i_length ) *
729                 (mtime_t)p_stream->i_scale /
730                 (mtime_t)p_stream->i_rate /
731                 (mtime_t)p_stream->i_samplesize;
732         }
733         else
734         {
735             i_length = (mtime_t)p_stream->i_idxnb *
736                        (mtime_t)p_stream->i_scale /
737                        (mtime_t)p_stream->i_rate;
738         }
739
740         msg_Dbg( p_input,
741                  "stream[%d] length:"I64Fd" (based on index)",
742                  i_stream,
743                  i_length );
744         i_maxlength = __MAX( i_maxlength, i_length );
745 #undef p_stream
746     }
747
748     return i_maxlength;
749 }
750
751 /*****************************************************************************
752  * AVIEnd: frees unused data
753  *****************************************************************************/
754 static void __AVIEnd ( vlc_object_t * p_this )
755 {
756     input_thread_t *    p_input = (input_thread_t *)p_this;
757     unsigned int i;
758     demux_sys_t *p_avi = p_input->p_demux_data  ;
759
760     if( p_avi->pp_info )
761     {
762         for( i = 0; i < p_avi->i_streams; i++ )
763         {
764             if( p_avi->pp_info[i] )
765             {
766                 if( p_avi->pp_info[i]->p_index )
767                 {
768                       free( p_avi->pp_info[i]->p_index );
769                 }
770                 free( p_avi->pp_info[i] );
771             }
772         }
773          free( p_avi->pp_info );
774     }
775 #ifdef __AVI_SUBTITLE__
776     if( p_avi->p_sub )
777     {
778         subtitle_Close( p_avi->p_sub );
779         p_avi->p_sub = NULL;
780     }
781 #endif
782     AVI_ChunkFreeRoot( p_input, &p_avi->ck_root );
783 }
784
785 /*****************************************************************************
786  * AVIInit: check file and initializes AVI structures
787  *****************************************************************************/
788 static int AVIInit( vlc_object_t * p_this )
789 {
790     input_thread_t *    p_input = (input_thread_t *)p_this;
791     avi_chunk_t         ck_riff;
792     avi_chunk_list_t    *p_riff = (avi_chunk_list_t*)&ck_riff;
793     avi_chunk_list_t    *p_hdrl, *p_movi;
794 #if 0
795     avi_chunk_list_t    *p_INFO;
796     avi_chunk_strz_t    *p_name;
797 #endif
798     avi_chunk_avih_t    *p_avih;
799     demux_sys_t *p_avi;
800     es_descriptor_t *p_es = NULL; /* avoid warning */
801     unsigned int i;
802 #ifdef __AVI_SUBTITLE__
803     mtime_t i_microsecperframe = 0; // for some subtitle format
804 #endif
805
806     vlc_bool_t b_stream_audio, b_stream_video;
807
808     p_input->pf_demux = AVIDemux_Seekable;
809     if( AVI_TestFile( p_input ) )
810     {
811         msg_Warn( p_input, "avi module discarded (invalid headr)" );
812         return VLC_EGENERIC;
813     }
814
815     /* Initialize access plug-in structures. */
816     if( p_input->i_mtu == 0 )
817     {
818         /* Improve speed. */
819         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
820     }
821
822     if( !( p_input->p_demux_data =
823                     p_avi = malloc( sizeof(demux_sys_t) ) ) )
824     {
825         msg_Err( p_input, "out of memory" );
826         return VLC_ENOMEM;
827     }
828     memset( p_avi, 0, sizeof( demux_sys_t ) );
829     p_avi->i_time = 0;
830     p_avi->i_pcr  = 0;
831     p_avi->b_seekable = ( ( p_input->stream.b_seekable )
832                         &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
833     p_avi->i_movi_lastchunk_pos = 0;
834
835     /* *** for unseekable stream, automaticaly use AVIDemux_interleaved *** */
836     if( !p_avi->b_seekable || config_GetInt( p_input, "avi-interleaved" ) )
837     {
838         p_input->pf_demux = AVIDemux_UnSeekable;
839     }
840
841     if( AVI_ChunkReadRoot( p_input, &p_avi->ck_root, p_avi->b_seekable ) )
842     {
843         msg_Err( p_input, "avi module discarded (invalid file)" );
844         return VLC_EGENERIC;
845     }
846     AVI_ChunkDumpDebug( p_input, &p_avi->ck_root );
847
848
849     p_riff  = (avi_chunk_list_t*)AVI_ChunkFind( &p_avi->ck_root,
850                                                 AVIFOURCC_RIFF, 0 );
851     p_hdrl  = (avi_chunk_list_t*)AVI_ChunkFind( p_riff,
852                                                 AVIFOURCC_hdrl, 0 );
853     p_movi  = (avi_chunk_list_t*)AVI_ChunkFind( p_riff,
854                                                 AVIFOURCC_movi, 0 );
855 #if 0
856     p_INFO  = (avi_chunk_list_t*)AVI_ChunkFind( p_riff,
857                                                 AVIFOURCC_INFO, 0 );
858     p_name  = (avi_chunk_strz_t*)AVI_ChunkFind( p_INFO,
859                                                 AVIFOURCC_INAM, 0 );
860     if( p_name )
861     {
862
863     }
864 #endif
865
866     if( !p_hdrl || !p_movi )
867     {
868         msg_Err( p_input, "avi module discarded (invalid file)" );
869         return VLC_EGENERIC;
870     }
871
872     if( !( p_avih = (avi_chunk_avih_t*)AVI_ChunkFind( p_hdrl,
873                                                       AVIFOURCC_avih, 0 ) ) )
874     {
875         msg_Err( p_input, "cannot find avih chunk" );
876         return VLC_EGENERIC;
877     }
878     p_avi->i_streams = AVI_ChunkCount( p_hdrl, AVIFOURCC_strl );
879     if( p_avih->i_streams != p_avi->i_streams )
880     {
881         msg_Warn( p_input,
882                   "found %d stream but %d are declared",
883                   p_avi->i_streams,
884                   p_avih->i_streams );
885     }
886     if( p_avi->i_streams == 0 )
887     {
888         AVIEnd( p_input );
889         msg_Err( p_input, "no stream defined!" );
890         return VLC_EGENERIC;
891     }
892
893     /*  create one program */
894     vlc_mutex_lock( &p_input->stream.stream_lock );
895     if( input_InitStream( p_input, 0 ) == -1)
896     {
897         vlc_mutex_unlock( &p_input->stream.stream_lock );
898         AVIEnd( p_input );
899         msg_Err( p_input, "cannot init stream" );
900         return VLC_EGENERIC;
901     }
902     if( input_AddProgram( p_input, 0, 0) == NULL )
903     {
904         vlc_mutex_unlock( &p_input->stream.stream_lock );
905         AVIEnd( p_input );
906         msg_Err( p_input, "cannot add program" );
907         return VLC_EGENERIC;
908     }
909     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
910     vlc_mutex_unlock( &p_input->stream.stream_lock );
911
912     /* print informations on streams */
913     msg_Dbg( p_input, "AVIH: %d stream, flags %s%s%s%s ",
914              p_avi->i_streams,
915              p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
916              p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
917              p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
918              p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
919     {
920         input_info_category_t *p_cat = input_InfoCategory( p_input, "Avi" );
921         input_AddInfo( p_cat, "Number of streams", "%d", p_avi->i_streams );
922         input_AddInfo( p_cat, "Flags", "%s%s%s%s",
923                        p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
924                        p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
925                        p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
926                        p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
927     }
928         
929     /* now read info on each stream and create ES */
930     p_avi->pp_info = calloc( p_avi->i_streams,
931                             sizeof( avi_stream_t* ) );
932     memset( p_avi->pp_info,
933             0,
934             sizeof( avi_stream_t* ) * p_avi->i_streams );
935
936     for( i = 0 ; i < p_avi->i_streams; i++ )
937     {
938         avi_chunk_list_t    *p_avi_strl;
939         avi_chunk_strh_t    *p_avi_strh;
940         avi_chunk_strf_auds_t    *p_avi_strf_auds;
941         avi_chunk_strf_vids_t    *p_avi_strf_vids;
942         int     i_init_size;
943         void    *p_init_data;
944 #define p_info  p_avi->pp_info[i]
945         p_info = malloc( sizeof(avi_stream_t ) );
946         memset( p_info, 0, sizeof( avi_stream_t ) );
947
948         p_avi_strl = (avi_chunk_list_t*)AVI_ChunkFind( p_hdrl,
949                                                        AVIFOURCC_strl, i );
950         p_avi_strh = (avi_chunk_strh_t*)AVI_ChunkFind( p_avi_strl,
951                                                        AVIFOURCC_strh, 0 );
952         p_avi_strf_auds = (avi_chunk_strf_auds_t*)
953             p_avi_strf_vids = (avi_chunk_strf_vids_t*)
954                 AVI_ChunkFind( p_avi_strl, AVIFOURCC_strf, 0 );
955
956         if( !p_avi_strl || !p_avi_strh ||
957                 ( !p_avi_strf_auds && !p_avi_strf_vids ) )
958         {
959             msg_Warn( p_input, "stream[%d] incomlete", i );
960             continue;
961         }
962
963         /* *** Init p_info *** */
964         p_info->i_rate  = p_avi_strh->i_rate;
965         p_info->i_scale = p_avi_strh->i_scale;
966         p_info->i_samplesize = p_avi_strh->i_samplesize;
967         msg_Dbg( p_input, "stream[%d] rate:%d scale:%d samplesize:%d",
968                  i,
969                  p_info->i_rate, p_info->i_scale, p_info->i_samplesize );
970         switch( p_avi_strh->i_type )
971         {
972             case( AVIFOURCC_auds ):
973                 p_info->i_cat = AUDIO_ES;
974                 p_info->i_fourcc =
975                     AVI_FourccGetCodec( AUDIO_ES,
976                                         p_avi_strf_auds->p_wf->wFormatTag );
977                 p_info->i_codec  = p_info->i_fourcc;
978                 i_init_size = p_avi_strf_auds->i_chunk_size;
979                 p_init_data = p_avi_strf_auds->p_wf;
980                 msg_Dbg( p_input, "stream[%d] audio(0x%x) %d channels %dHz %dbits",
981                         i,
982                         p_avi_strf_auds->p_wf->wFormatTag,
983                         p_avi_strf_auds->p_wf->nChannels,
984                         p_avi_strf_auds->p_wf->nSamplesPerSec,
985                         p_avi_strf_auds->p_wf->wBitsPerSample );
986                 {
987                     char hepp[sizeof("Stream") + 10];
988                     input_info_category_t *p_cat;
989                     sprintf(hepp, "Stream %d", i);
990                     p_cat = input_InfoCategory( p_input, hepp);
991                     input_AddInfo( p_cat, "Type", "audio(0x%x)",
992                                    p_avi_strf_auds->p_wf->wFormatTag );
993                     input_AddInfo( p_cat, "Codec", "%4.4s",
994                                    (const char*)&(p_info->i_codec) );
995                     input_AddInfo( p_cat, "Channels", "%d",
996                                    p_avi_strf_auds->p_wf->nChannels );
997                     input_AddInfo( p_cat, "Samplerate", "%d",
998                                    p_avi_strf_auds->p_wf->nSamplesPerSec );
999                     input_AddInfo( p_cat, "Bits Per Sample", "%d",
1000                                    p_avi_strf_auds->p_wf->wBitsPerSample );
1001                 }
1002                 break;
1003
1004             case( AVIFOURCC_vids ):
1005                 p_info->i_cat = VIDEO_ES;
1006                 /* XXX quick hack for playing ffmpeg video, I don't know
1007                     who is doing something wrong */
1008                 p_info->i_samplesize = 0;
1009                 p_info->i_fourcc = p_avi_strf_vids->p_bih->biCompression;
1010                 p_info->i_codec =
1011                     AVI_FourccGetCodec( VIDEO_ES, p_info->i_fourcc );
1012                 i_init_size = p_avi_strf_vids->i_chunk_size;
1013                 p_init_data = p_avi_strf_vids->p_bih;
1014                 msg_Dbg( p_input, "stream[%d] video(%4.4s) %dx%d %dbpp %ffps",
1015                         i,
1016                          (char*)&p_avi_strf_vids->p_bih->biCompression,
1017                          p_avi_strf_vids->p_bih->biWidth,
1018                          p_avi_strf_vids->p_bih->biHeight,
1019                          p_avi_strf_vids->p_bih->biBitCount,
1020                          (float)p_info->i_rate /
1021                              (float)p_info->i_scale );
1022                 {
1023                     char hepp[sizeof("Stream") + 10];
1024                     input_info_category_t *p_cat;
1025                     sprintf(hepp, "stream %d", i);
1026                     p_cat = input_InfoCategory( p_input, hepp);
1027                     input_AddInfo( p_cat, "Type", "video" );
1028                     input_AddInfo( p_cat, "Codec", "%4.4s",
1029                                    (const char*)&(p_info->i_codec) );
1030                     input_AddInfo( p_cat, "Resolution", "%dx%d",
1031                                    p_avi_strf_vids->p_bih->biWidth,
1032                                    p_avi_strf_vids->p_bih->biHeight );
1033                     input_AddInfo( p_cat, "Frame Rate", "%f",
1034                                    (float)p_info->i_rate /
1035                                        (float)p_info->i_scale );
1036                     input_AddInfo( p_cat, "Bits Per Pixel", "%d",
1037                                    p_avi_strf_vids->p_bih->biBitCount );
1038                 }
1039 #ifdef __AVI_SUBTITLE__
1040                 if( i_microsecperframe == 0 )
1041                 {
1042                     i_microsecperframe = (mtime_t)1000000 *
1043                                          (mtime_t)p_info->i_scale /
1044                                          (mtime_t)p_info->i_rate;
1045                 }
1046 #endif
1047                 break;
1048             default:
1049                 msg_Warn( p_input, "stream[%d] unknown type", i );
1050                 p_info->i_cat = UNKNOWN_ES;
1051                 i_init_size = 0;
1052                 p_init_data = NULL;
1053                 {
1054                     char psz_cat[32]; /* We'll clip i just in case */
1055                     input_info_category_t *p_cat;
1056                     sprintf( psz_cat, "stream %d", __MIN( i, 100000 ) );
1057                     p_cat = input_InfoCategory( p_input, psz_cat );
1058                     input_AddInfo( p_cat, "Type", "unknown" );
1059                 }
1060                 break;
1061         }
1062         p_info->b_activated = VLC_FALSE;
1063         /* add one ES */
1064         vlc_mutex_lock( &p_input->stream.stream_lock );
1065         p_info->p_es =
1066             p_es = input_AddES( p_input,
1067                                 p_input->stream.p_selected_program, 1+i,
1068                                 0 );
1069         vlc_mutex_unlock( &p_input->stream.stream_lock );
1070         p_es->i_stream_id =i; /* XXX: i don't use it */
1071         p_es->i_fourcc = p_info->i_fourcc;
1072         p_es->i_cat = p_info->i_cat;
1073         if( p_es->i_cat == AUDIO_ES )
1074         {
1075             p_es->p_waveformatex = malloc( i_init_size );
1076             memcpy( p_es->p_waveformatex, p_init_data, i_init_size );
1077         }
1078         else if( p_es->i_cat == VIDEO_ES )
1079         {
1080             p_es->p_bitmapinfoheader = malloc( i_init_size );
1081             memcpy( p_es->p_bitmapinfoheader, p_init_data, i_init_size );
1082         }
1083 #undef p_info
1084     }
1085
1086 #ifdef __AVI_SUBTITLE__
1087     if( ( p_avi->p_sub = subtitle_New( p_input, NULL, i_microsecperframe ) ) )
1088     {
1089         subtitle_Select( p_avi->p_sub );
1090     }
1091 #endif
1092
1093     if( config_GetInt( p_input, "avi-index" ) )
1094     {
1095         if( p_avi->b_seekable )
1096         {
1097             AVI_IndexCreate( p_input );
1098         }
1099         else
1100         {
1101             msg_Warn( p_input, "cannot create index (unseekable stream)" );
1102             AVI_IndexLoad( p_input );
1103         }
1104     }
1105     else
1106     {
1107         AVI_IndexLoad( p_input );
1108     }
1109
1110     /* *** movie length in sec *** */
1111     p_avi->i_length = AVI_MovieGetLength( p_input, p_avi );
1112     if( p_avi->i_length < (mtime_t)p_avih->i_totalframes *
1113                           (mtime_t)p_avih->i_microsecperframe /
1114                           (mtime_t)1000000 )
1115     {
1116         msg_Warn( p_input, "broken or missing index, 'seek' will be axproximative or will have strange behavour" );
1117     }
1118
1119     vlc_mutex_lock( &p_input->stream.stream_lock );
1120     if( p_avi->i_length )
1121     {
1122         p_input->stream.i_mux_rate =
1123             p_input->stream.p_selected_area->i_size / 50 / p_avi->i_length;
1124     }
1125     else
1126     {
1127         p_input->stream.i_mux_rate = 0;
1128     }
1129     vlc_mutex_unlock( &p_input->stream.stream_lock );
1130
1131     b_stream_audio = VLC_FALSE;
1132     b_stream_video = VLC_FALSE;
1133
1134     for( i = 0; i < p_avi->i_streams; i++ )
1135     {
1136 #define p_info  p_avi->pp_info[i]
1137         switch( p_info->p_es->i_cat )
1138         {
1139             case( VIDEO_ES ):
1140
1141                 if( !b_stream_video )
1142                 {
1143                     b_stream_video = AVI_StreamStart( p_input, p_avi, i );
1144                 }
1145                 break;
1146
1147             case( AUDIO_ES ):
1148                 if( !b_stream_audio )
1149                 {
1150                     b_stream_audio = AVI_StreamStart( p_input, p_avi, i );
1151                 }
1152                 break;
1153             default:
1154                 break;
1155         }
1156 #undef p_info
1157     }
1158
1159     if( !b_stream_video )
1160     {
1161         msg_Warn( p_input, "no video stream found" );
1162     }
1163     if( !b_stream_audio )
1164     {
1165         msg_Warn( p_input, "no audio stream found!" );
1166     }
1167
1168     vlc_mutex_lock( &p_input->stream.stream_lock );
1169     p_input->stream.p_selected_program->b_is_ok = 1;
1170     vlc_mutex_unlock( &p_input->stream.stream_lock );
1171
1172     if( p_avi->b_seekable )
1173     {
1174         AVI_ChunkGoto( p_input, p_movi );
1175     }
1176     else
1177     {
1178         // already at begining of p_movi
1179     }
1180     AVI_SkipBytes( p_input, 12 ); // enter in p_movi
1181
1182     p_avi->i_movi_begin = p_movi->i_chunk_pos;
1183     return VLC_SUCCESS;
1184 }
1185
1186
1187
1188
1189 /*****************************************************************************
1190  * Function to convert pts to chunk or byte
1191  *****************************************************************************/
1192
1193 static inline mtime_t AVI_PTSToChunk( avi_stream_t *p_info,
1194                                         mtime_t i_pts )
1195 {
1196     return (mtime_t)((int64_t)i_pts *
1197                      (int64_t)p_info->i_rate /
1198                      (int64_t)p_info->i_scale /
1199                      (int64_t)1000000 );
1200 }
1201 static inline mtime_t AVI_PTSToByte( avi_stream_t *p_info,
1202                                        mtime_t i_pts )
1203 {
1204     return (mtime_t)((int64_t)i_pts *
1205                      (int64_t)p_info->i_rate /
1206                      (int64_t)p_info->i_scale /
1207                      (int64_t)1000000 *
1208                      (int64_t)p_info->i_samplesize );
1209 }
1210
1211 static mtime_t AVI_GetDPTS( avi_stream_t *p_stream, int i_count )
1212 {
1213     if( p_stream->i_samplesize )
1214     {
1215         return (mtime_t)( (int64_t)1000000 *
1216                    (int64_t)i_count *
1217                    (int64_t)p_stream->i_scale /
1218                    (int64_t)p_stream->i_rate /
1219                    (int64_t)p_stream->i_samplesize );
1220     }
1221     else
1222     {
1223         return (mtime_t)( (int64_t)1000000 *
1224                    (int64_t)i_count *
1225                    (int64_t)p_stream->i_scale /
1226                    (int64_t)p_stream->i_rate);
1227     }
1228
1229 }
1230
1231 static mtime_t AVI_GetPTS( avi_stream_t *p_info )
1232 {
1233
1234     if( p_info->i_samplesize )
1235     {
1236         /* we need a valid entry we will emulate one */
1237         int64_t i_len;
1238         if( p_info->i_idxposc == p_info->i_idxnb )
1239         {
1240             if( p_info->i_idxposc )
1241             {
1242                 /* use the last entry */
1243                 i_len = p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal
1244                             + p_info->p_index[p_info->i_idxnb - 1].i_length
1245                             + p_info->i_idxposb; /* should be 0 */
1246             }
1247             else
1248             {
1249                 i_len = p_info->i_idxposb;
1250                 /* no valid entry use only offset*/
1251             }
1252         }
1253         else
1254         {
1255             i_len = p_info->p_index[p_info->i_idxposc].i_lengthtotal
1256                                 + p_info->i_idxposb;
1257         }
1258         return (mtime_t)( (int64_t)1000000 *
1259                   (int64_t)i_len *
1260                    (int64_t)p_info->i_scale /
1261                    (int64_t)p_info->i_rate /
1262                    (int64_t)p_info->i_samplesize );
1263     }
1264     else
1265     {
1266         /* even if p_info->i_idxposc isn't valid, there isn't any problem */
1267         return (mtime_t)( (int64_t)1000000 *
1268                    (int64_t)(p_info->i_idxposc ) *
1269                    (int64_t)p_info->i_scale /
1270                    (int64_t)p_info->i_rate);
1271     }
1272 }
1273
1274 static int AVI_StreamChunkFind( input_thread_t *p_input,
1275                                 unsigned int i_stream )
1276 {
1277     demux_sys_t *p_avi = p_input->p_demux_data;
1278     avi_packet_t avi_pk;
1279
1280     /* find first chunk of i_stream that isn't in index */
1281
1282     if( p_avi->i_movi_lastchunk_pos >= p_avi->i_movi_begin )
1283     {
1284         AVI_SeekAbsolute( p_input, p_avi->i_movi_lastchunk_pos );
1285         if( AVI_PacketNext( p_input ) )
1286         {
1287             return VLC_EGENERIC;
1288         }
1289     }
1290     else
1291     {
1292         AVI_SeekAbsolute( p_input, p_avi->i_movi_begin );
1293     }
1294
1295     for( ;; )
1296     {
1297
1298         if( AVI_PacketGetHeader( p_input, &avi_pk ) )
1299         {
1300             msg_Warn( p_input, "cannot get packet header" );
1301             return VLC_EGENERIC;
1302         }
1303         if( avi_pk.i_stream >= p_avi->i_streams ||
1304             ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
1305         {
1306             switch( avi_pk.i_fourcc )
1307             {
1308                 case AVIFOURCC_LIST:
1309                     AVI_SkipBytes( p_input, 12 );
1310                     break;
1311                 default:
1312                     if( AVI_PacketNext( p_input ) )
1313                     {
1314                         return VLC_EGENERIC;
1315                     }
1316                     break;
1317             }
1318         }
1319         else
1320         {
1321             /* add this chunk to the index */
1322             AVIIndexEntry_t index;
1323
1324             index.i_id = avi_pk.i_fourcc;
1325             index.i_flags =
1326                AVI_GetKeyFlag(p_avi->pp_info[avi_pk.i_stream]->i_codec,
1327                               avi_pk.i_peek);
1328             index.i_pos = avi_pk.i_pos;
1329             index.i_length = avi_pk.i_size;
1330             AVI_IndexAddEntry( p_avi, avi_pk.i_stream, &index );
1331
1332             if( avi_pk.i_stream == i_stream  )
1333             {
1334                 return VLC_SUCCESS;
1335             }
1336
1337             if( AVI_PacketNext( p_input ) )
1338             {
1339                 return VLC_EGENERIC;
1340             }
1341         }
1342     }
1343 }
1344
1345
1346 /* be sure that i_ck will be a valid index entry */
1347 static int AVI_SetStreamChunk( input_thread_t    *p_input,
1348                                unsigned int i_stream,
1349                                unsigned int i_ck )
1350 {
1351     demux_sys_t *p_avi = p_input->p_demux_data;
1352     avi_stream_t *p_stream = p_avi->pp_info[i_stream];
1353
1354     p_stream->i_idxposc = i_ck;
1355     p_stream->i_idxposb = 0;
1356
1357     if(  i_ck >= p_stream->i_idxnb )
1358     {
1359         p_stream->i_idxposc = p_stream->i_idxnb - 1;
1360         do
1361         {
1362             p_stream->i_idxposc++;
1363             if( AVI_StreamChunkFind( p_input, i_stream ) )
1364             {
1365                 return VLC_EGENERIC;
1366             }
1367
1368         } while( p_stream->i_idxposc < i_ck );
1369     }
1370
1371     return VLC_SUCCESS;
1372 }
1373
1374
1375 /* XXX FIXME up to now, we assume that all chunk are one after one */
1376 static int AVI_SetStreamBytes( input_thread_t    *p_input,
1377                                unsigned int i_stream,
1378                                off_t   i_byte )
1379 {
1380     demux_sys_t *p_avi = p_input->p_demux_data;
1381     avi_stream_t *p_stream = p_avi->pp_info[i_stream];
1382
1383     if( ( p_stream->i_idxnb > 0 )
1384         &&( i_byte < p_stream->p_index[p_stream->i_idxnb - 1].i_lengthtotal +
1385                 p_stream->p_index[p_stream->i_idxnb - 1].i_length ) )
1386     {
1387         /* index is valid to find the ck */
1388         /* uses dichototmie to be fast enougth */
1389         int i_idxposc = __MIN( p_stream->i_idxposc, p_stream->i_idxnb - 1 );
1390         int i_idxmax  = p_stream->i_idxnb;
1391         int i_idxmin  = 0;
1392         for( ;; )
1393         {
1394             if( p_stream->p_index[i_idxposc].i_lengthtotal > i_byte )
1395             {
1396                 i_idxmax  = i_idxposc ;
1397                 i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
1398             }
1399             else
1400             {
1401                 if( p_stream->p_index[i_idxposc].i_lengthtotal +
1402                         p_stream->p_index[i_idxposc].i_length <= i_byte)
1403                 {
1404                     i_idxmin  = i_idxposc ;
1405                     i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
1406                 }
1407                 else
1408                 {
1409                     p_stream->i_idxposc = i_idxposc;
1410                     p_stream->i_idxposb = i_byte -
1411                             p_stream->p_index[i_idxposc].i_lengthtotal;
1412                     return VLC_SUCCESS;
1413                 }
1414             }
1415         }
1416
1417     }
1418     else
1419     {
1420         p_stream->i_idxposc = p_stream->i_idxnb - 1;
1421         p_stream->i_idxposb = 0;
1422         do
1423         {
1424             p_stream->i_idxposc++;
1425             if( AVI_StreamChunkFind( p_input, i_stream ) )
1426             {
1427                 return VLC_EGENERIC;
1428             }
1429
1430         } while( p_stream->p_index[p_stream->i_idxposc].i_lengthtotal +
1431                     p_stream->p_index[p_stream->i_idxposc].i_length <= i_byte );
1432
1433         p_stream->i_idxposb = i_byte -
1434                        p_stream->p_index[p_stream->i_idxposc].i_lengthtotal;
1435         return VLC_SUCCESS;
1436     }
1437 }
1438
1439 static int AVI_StreamSeek( input_thread_t *p_input,
1440                            demux_sys_t  *p_avi,
1441                            int i_stream,
1442                            mtime_t i_date )
1443 {
1444 #define p_stream    p_avi->pp_info[i_stream]
1445     mtime_t i_oldpts;
1446
1447     i_oldpts = AVI_GetPTS( p_stream );
1448
1449     if( !p_stream->i_samplesize )
1450     {
1451         if( AVI_SetStreamChunk( p_input,
1452                                 i_stream,
1453                                 AVI_PTSToChunk( p_stream, i_date ) ) )
1454         {
1455             return VLC_EGENERIC;
1456         }
1457
1458         /* search key frame */
1459         msg_Dbg( p_input,
1460                  "old:"I64Fd" %s new "I64Fd,
1461                  i_oldpts,
1462                  i_oldpts > i_date ? ">" : "<",
1463                  i_date );
1464
1465         if( i_date < i_oldpts )
1466         {
1467             while( p_stream->i_idxposc > 0 &&
1468                !( p_stream->p_index[p_stream->i_idxposc].i_flags &
1469                                                             AVIIF_KEYFRAME ) )
1470             {
1471                 if( AVI_SetStreamChunk( p_input,
1472                                         i_stream,
1473                                         p_stream->i_idxposc - 1 ) )
1474                 {
1475                     return VLC_EGENERIC;
1476                 }
1477             }
1478         }
1479         else
1480         {
1481             while( p_stream->i_idxposc < p_stream->i_idxnb &&
1482                     !( p_stream->p_index[p_stream->i_idxposc].i_flags &
1483                                                             AVIIF_KEYFRAME ) )
1484             {
1485                 if( AVI_SetStreamChunk( p_input,
1486                                         i_stream,
1487                                         p_stream->i_idxposc + 1 ) )
1488                 {
1489                     return VLC_EGENERIC;
1490                 }
1491             }
1492         }
1493     }
1494     else
1495     {
1496         if( AVI_SetStreamBytes( p_input,
1497                                 i_stream,
1498                                 AVI_PTSToByte( p_stream, i_date ) ) )
1499         {
1500             return VLC_EGENERIC;
1501         }
1502     }
1503     return VLC_SUCCESS;
1504 #undef p_stream
1505 }
1506
1507 /*****************************************************************************
1508  * AVISeek: goto to i_date or i_percent
1509  *****************************************************************************
1510  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1511  *****************************************************************************/
1512 static int    AVISeek   ( input_thread_t *p_input,
1513                           mtime_t i_date, int i_percent )
1514 {
1515
1516     demux_sys_t *p_avi = p_input->p_demux_data;
1517     unsigned int i_stream;
1518     msg_Dbg( p_input,
1519              "seek requested: "I64Fd" secondes %d%%",
1520              i_date / 1000000,
1521              i_percent );
1522
1523     if( p_avi->b_seekable )
1524     {
1525         if( !p_avi->i_length )
1526         {
1527             avi_stream_t *p_stream;
1528             uint64_t i_pos;
1529
1530             /* use i_percent to create a true i_date */
1531             msg_Warn( p_input,
1532                       "mmh, seeking without index at %d%%"
1533                       " work only for interleaved file", i_percent );
1534
1535             if( i_percent >= 100 )
1536             {
1537                 msg_Warn( p_input, "cannot seek so far !" );
1538                 return( -1 );
1539             }
1540             i_percent = __MAX( i_percent, 0 );
1541
1542             /* try to find chunk that is at i_percent or the file */
1543             i_pos = __MAX( i_percent *
1544                            p_input->stream.p_selected_area->i_size / 100,
1545                            p_avi->i_movi_begin );
1546             /* search first selected stream */
1547             for( i_stream = 0, p_stream = NULL;
1548                         i_stream < p_avi->i_streams; i_stream++ )
1549             {
1550                 p_stream = p_avi->pp_info[i_stream];
1551                 if( p_stream->b_activated )
1552                 {
1553                     break;
1554                 }
1555             }
1556             if( !p_stream || !p_stream->b_activated )
1557             {
1558                 msg_Warn( p_input, "cannot find any selected stream" );
1559                 return( -1 );
1560             }
1561
1562             /* be sure that the index exit */
1563             if( AVI_SetStreamChunk( p_input,
1564                                     i_stream,
1565                                     0 ) )
1566             {
1567                 msg_Warn( p_input, "cannot seek" );
1568                 return( -1 );
1569             }
1570
1571             while( i_pos >= p_stream->p_index[p_stream->i_idxposc].i_pos +
1572                p_stream->p_index[p_stream->i_idxposc].i_length + 8 )
1573             {
1574                 /* search after i_idxposc */
1575                 if( AVI_SetStreamChunk( p_input,
1576                                         i_stream, p_stream->i_idxposc + 1 ) )
1577                 {
1578                     msg_Warn( p_input, "cannot seek" );
1579                     return( -1 );
1580                 }
1581             }
1582             i_date = AVI_GetPTS( p_stream );
1583             /* TODO better support for i_samplesize != 0 */
1584             msg_Dbg( p_input, "estimate date "I64Fd, i_date );
1585         }
1586
1587 #define p_stream    p_avi->pp_info[i_stream]
1588         p_avi->i_time = 0;
1589         /* seek for chunk based streams */
1590         for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
1591         {
1592             if( p_stream->b_activated && !p_stream->i_samplesize )
1593 //            if( p_stream->b_activated )
1594             {
1595                 AVI_StreamSeek( p_input, p_avi, i_stream, i_date );
1596                 p_avi->i_time = __MAX( AVI_GetPTS( p_stream ),
1597                                         p_avi->i_time );
1598             }
1599         }
1600 #if 1
1601         if( p_avi->i_time )
1602         {
1603             i_date = p_avi->i_time;
1604         }
1605         /* seek for bytes based streams */
1606         for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
1607         {
1608             if( p_stream->b_activated && p_stream->i_samplesize )
1609             {
1610                 AVI_StreamSeek( p_input, p_avi, i_stream, i_date );
1611 //                p_avi->i_time = __MAX( AVI_GetPTS( p_stream ), p_avi->i_time );
1612             }
1613         }
1614         msg_Dbg( p_input, "seek: "I64Fd" secondes", p_avi->i_time /1000000 );
1615         /* set true movie time */
1616 #endif
1617         if( !p_avi->i_time )
1618         {
1619             p_avi->i_time = i_date;
1620         }
1621 #undef p_stream
1622         return( 1 );
1623     }
1624     else
1625     {
1626         msg_Err( p_input, "shouldn't yet be executed" );
1627         return( -1 );
1628     }
1629 }
1630
1631 #if 0
1632 static pes_packet_t *PES_split( input_thread_t *p_input, avi_stream_t *p_stream, pes_packet_t *p_pes )
1633 {
1634     pes_packet_t  *p_pes2;
1635     data_packet_t *p_data;
1636     int           i_nb_data;
1637
1638     if( p_pes->i_nb_data < 2 )
1639     {
1640         return( NULL );
1641     }
1642     p_pes2 = input_NewPES( p_input->p_method_data );
1643     p_pes2->i_pts = p_pes->i_pts;
1644     p_pes2->i_dts = p_pes->i_dts;
1645     p_pes2->i_nb_data = p_pes->i_nb_data/2;
1646     p_pes2->i_pes_size = 0;
1647     for( i_nb_data = 0, p_data = p_pes->p_first;
1648          i_nb_data < p_pes2->i_nb_data;
1649          i_nb_data++, p_data = p_data->p_next )
1650     {
1651         p_pes2->i_pes_size +=
1652             p_data->p_payload_end - p_data->p_payload_start;
1653         p_pes2->p_last = p_data;
1654     }
1655     p_pes2->p_first = p_pes->p_first;
1656     p_pes2->p_last->p_next = NULL;
1657
1658     p_pes->p_first = p_data;
1659     p_pes->i_pes_size -= p_pes2->i_pes_size;
1660     p_pes->i_nb_data -= p_pes2->i_nb_data;
1661 //    p_pes->i_pts += AVI_GetDPTS( p_stream, p_pes2->i_pes_size );
1662 //    p_pes->i_dts += AVI_GetDPTS( p_stream, p_pes2->i_pes_size );
1663     p_pes->i_pts = 0;
1664     p_pes->i_dts = 0;
1665     return( p_pes2 );
1666 }
1667 #endif
1668
1669 /*****************************************************************************
1670  * AVIDemux_Seekable: reads and demuxes data packets for stream seekable
1671  *****************************************************************************
1672  * AVIDemux: reads and demuxes data packets
1673  *****************************************************************************
1674  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1675  *****************************************************************************/
1676 typedef struct avi_stream_toread_s
1677 {
1678     vlc_bool_t b_ok;
1679
1680     int i_toread;
1681
1682     off_t i_posf; // where we will read :
1683                   // if i_idxposb == 0 : begining of chunk (+8 to acces data)
1684                   // else : point on data directly
1685 } avi_stream_toread_t;
1686
1687 static int AVIDemux_Seekable( input_thread_t *p_input )
1688 {
1689     unsigned int i_stream_count;
1690     unsigned int i_stream;
1691     vlc_bool_t b_stream;
1692
1693     // cannot be more than 100 stream (dcXX or wbXX)
1694     avi_stream_toread_t toread[100];
1695
1696     demux_sys_t *p_avi = p_input->p_demux_data;
1697
1698     /* detect new selected/unselected streams */
1699     for( i_stream = 0,i_stream_count= 0;
1700             i_stream < p_avi->i_streams; i_stream++ )
1701     {
1702 #define p_stream    p_avi->pp_info[i_stream]
1703         if( p_stream->p_es )
1704         {
1705             if( p_stream->p_es->p_decoder_fifo &&
1706                 !p_stream->b_activated )
1707             {
1708                 AVI_StreamStart( p_input, p_avi, i_stream );
1709             }
1710             else
1711             if( !p_stream->p_es->p_decoder_fifo &&
1712                 p_stream->b_activated )
1713             {
1714                 AVI_StreamStop( p_input, p_avi, i_stream );
1715             }
1716         }
1717         if( p_stream->b_activated )
1718         {
1719             i_stream_count++;
1720         }
1721 #undef  p_stream
1722     }
1723
1724     if( i_stream_count <= 0 )
1725     {
1726         msg_Warn( p_input, "no track selected, exiting..." );
1727         return( 0 );
1728     }
1729
1730     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
1731     {
1732         mtime_t i_date;
1733         int i_percent;
1734         /* first wait for empty buffer, arbitrary time FIXME */
1735 //        msleep( DEFAULT_PTS_DELAY );
1736
1737         i_date = (mtime_t)1000000 *
1738                  (mtime_t)p_avi->i_length *
1739                  (mtime_t)AVI_TellAbsolute( p_input ) /
1740                  (mtime_t)p_input->stream.p_selected_area->i_size;
1741         i_percent = 100 * AVI_TellAbsolute( p_input ) /
1742                         p_input->stream.p_selected_area->i_size;
1743
1744 //        input_ClockInit( p_input->stream.p_selected_program );
1745         AVISeek( p_input, i_date, i_percent);
1746
1747 #ifdef __AVI_SUBTITLE__
1748         if( p_avi->p_sub )
1749         {
1750             subtitle_Seek( p_avi->p_sub, p_avi->i_time );
1751         }
1752 #endif
1753     }
1754
1755
1756     /* wait for the good time */
1757
1758     p_avi->i_pcr = p_avi->i_time * 9 / 100;
1759
1760     input_ClockManageRef( p_input,
1761                           p_input->stream.p_selected_program,
1762                           p_avi->i_pcr );
1763
1764
1765     p_avi->i_time += 25*1000;  /* read 25ms */
1766
1767 #ifdef __AVI_SUBTITLE__
1768     if( p_avi->p_sub )
1769     {
1770         subtitle_Demux( p_avi->p_sub, p_avi->i_time );
1771     }
1772 #endif
1773     /* init toread */
1774     for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
1775     {
1776 #define p_stream    p_avi->pp_info[i_stream]
1777         mtime_t i_dpts;
1778
1779         toread[i_stream].b_ok = p_stream->b_activated;
1780
1781         if( p_stream->i_idxposc < p_stream->i_idxnb )
1782         {
1783             toread[i_stream].i_posf =
1784                 p_stream->p_index[p_stream->i_idxposc].i_pos;
1785            if( p_stream->i_idxposb > 0 )
1786            {
1787                 toread[i_stream].i_posf += 8 + p_stream->i_idxposb;
1788            }
1789         }
1790         else
1791         {
1792             toread[i_stream].i_posf = -1;
1793         }
1794
1795         i_dpts = p_avi->i_time - AVI_GetPTS( p_stream  );
1796
1797         if( p_stream->i_samplesize )
1798         {
1799             toread[i_stream].i_toread = AVI_PTSToByte( p_stream,
1800                                                        __ABS( i_dpts ) );
1801         }
1802         else
1803         {
1804             toread[i_stream].i_toread = AVI_PTSToChunk( p_stream,
1805                                                         __ABS( i_dpts ) );
1806         }
1807
1808         if( i_dpts < 0 )
1809         {
1810             toread[i_stream].i_toread *= -1;
1811         }
1812 #undef  p_stream
1813     }
1814
1815     b_stream = VLC_FALSE;
1816
1817     for( ;; )
1818     {
1819 #define p_stream    p_avi->pp_info[i_stream]
1820         vlc_bool_t       b_done;
1821         pes_packet_t    *p_pes;
1822         off_t i_pos;
1823         unsigned int i;
1824         size_t i_size;
1825
1826         /* search for first chunk to be read */
1827         for( i = 0, b_done = VLC_TRUE, i_pos = -1; i < p_avi->i_streams; i++ )
1828         {
1829             if( !toread[i].b_ok ||
1830                 AVI_GetDPTS( p_avi->pp_info[i],
1831                              toread[i].i_toread ) <= -25 * 1000 )
1832             {
1833                 continue;
1834             }
1835
1836             if( toread[i].i_toread > 0 )
1837             {
1838                 b_done = VLC_FALSE; // not yet finished
1839             }
1840
1841             if( toread[i].i_posf > 0 )
1842             {
1843                 if( i_pos == -1 || i_pos > toread[i_stream].i_posf )
1844                 {
1845                     i_stream = i;
1846                     i_pos = toread[i].i_posf;
1847                 }
1848             }
1849         }
1850
1851         if( b_done )
1852         {
1853 //            return( b_stream ? 1 : 0 );
1854             return( 1 );
1855         }
1856
1857         if( i_pos == -1 )
1858         {
1859             /* no valid index, we will parse directly the stream
1860              * in case we fail we will disable all finished stream */
1861             if( p_avi->i_movi_lastchunk_pos >= p_avi->i_movi_begin )
1862             {
1863                 AVI_SeekAbsolute( p_input, p_avi->i_movi_lastchunk_pos );
1864                 if( AVI_PacketNext( p_input ) )
1865                 {
1866                     return( AVI_StreamStopFinishedStreams( p_input, p_avi ) ? 0 : 1 );
1867                 }
1868             }
1869             else
1870             {
1871                 AVI_SeekAbsolute( p_input, p_avi->i_movi_begin );
1872             }
1873
1874             for( ;; )
1875             {
1876                 avi_packet_t avi_pk;
1877
1878                 if( AVI_PacketGetHeader( p_input, &avi_pk ) )
1879                 {
1880                     msg_Warn( p_input,
1881                              "cannot get packet header, track disabled" );
1882                     return( AVI_StreamStopFinishedStreams( p_input, p_avi ) ? 0 : 1 );
1883                 }
1884                 if( avi_pk.i_stream >= p_avi->i_streams ||
1885                     ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
1886                 {
1887                     switch( avi_pk.i_fourcc )
1888                     {
1889                         case AVIFOURCC_LIST:
1890                             AVI_SkipBytes( p_input, 12 );
1891                             break;
1892                         default:
1893                             if( AVI_PacketNext( p_input ) )
1894                             {
1895                                 msg_Warn( p_input,
1896                                           "cannot skip packet, track disabled" );
1897                                 return( AVI_StreamStopFinishedStreams( p_input, p_avi ) ? 0 : 1 );
1898                             }
1899                             break;
1900                     }
1901                     continue;
1902                 }
1903                 else
1904                 {
1905                     /* add this chunk to the index */
1906                     AVIIndexEntry_t index;
1907
1908                     index.i_id = avi_pk.i_fourcc;
1909                     index.i_flags =
1910                        AVI_GetKeyFlag(p_avi->pp_info[avi_pk.i_stream]->i_codec,
1911                                       avi_pk.i_peek);
1912                     index.i_pos = avi_pk.i_pos;
1913                     index.i_length = avi_pk.i_size;
1914                     AVI_IndexAddEntry( p_avi, avi_pk.i_stream, &index );
1915
1916                     i_stream = avi_pk.i_stream;
1917                     /* do we will read this data ? */
1918                     if( AVI_GetDPTS( p_stream,
1919                              toread[i_stream].i_toread ) > -25 * 1000 )
1920                     {
1921                         break;
1922                     }
1923                     else
1924                     {
1925                         if( AVI_PacketNext( p_input ) )
1926                         {
1927                             msg_Warn( p_input,
1928                                       "cannot skip packet, track disabled" );
1929                             return( AVI_StreamStopFinishedStreams( p_input, p_avi ) ? 0 : 1 );
1930                         }
1931                     }
1932                 }
1933             }
1934
1935         }
1936         else
1937         {
1938             AVI_SeekAbsolute( p_input, i_pos );
1939         }
1940
1941         /* read thoses data */
1942         if( p_stream->i_samplesize )
1943         {
1944             int i_toread;
1945
1946             if( ( i_toread = toread[i_stream].i_toread ) <= 0 )
1947             {
1948                 if( p_stream->i_samplesize > 1 )
1949                 {
1950                     i_toread = p_stream->i_samplesize;
1951                 }
1952                 else
1953                 {
1954                     i_toread = __MAX( AVI_PTSToByte( p_stream, 20 * 1000 ), 100 );
1955                 }
1956             }
1957             i_size = __MIN( p_stream->p_index[p_stream->i_idxposc].i_length -
1958                                 p_stream->i_idxposb,
1959                             i_toread );
1960         }
1961         else
1962         {
1963             i_size = p_stream->p_index[p_stream->i_idxposc].i_length;
1964         }
1965
1966         if( p_stream->i_idxposb == 0 )
1967         {
1968             i_size += 8; // need to read and skip header
1969         }
1970
1971         if( input_ReadInPES( p_input, &p_pes, __EVEN( i_size ) ) < 0 )
1972         {
1973             msg_Warn( p_input, "failled reading data" );
1974             toread[i_stream].b_ok = VLC_FALSE;
1975             continue;
1976         }
1977
1978         if( i_size % 2 )    // read was padded on word boundary
1979         {
1980             p_pes->p_last->p_payload_end--;
1981             p_pes->i_pes_size--;
1982         }
1983         // skip header
1984         if( p_stream->i_idxposb == 0 )
1985         {
1986             p_pes->p_first->p_payload_start += 8;
1987             p_pes->i_pes_size -= 8;
1988         }
1989
1990         p_pes->i_pts = AVI_GetPTS( p_stream );
1991
1992         /* read data */
1993         if( p_stream->i_samplesize )
1994         {
1995             if( p_stream->i_idxposb == 0 )
1996             {
1997                 i_size -= 8;
1998             }
1999             toread[i_stream].i_toread -= i_size;
2000             p_stream->i_idxposb += i_size;
2001             if( p_stream->i_idxposb >=
2002                     p_stream->p_index[p_stream->i_idxposc].i_length )
2003             {
2004                 p_stream->i_idxposb = 0;
2005                 p_stream->i_idxposc++;
2006             }
2007         }
2008         else
2009         {
2010             toread[i_stream].i_toread--;
2011             p_stream->i_idxposc++;
2012         }
2013
2014         if( p_stream->i_idxposc < p_stream->i_idxnb)
2015         {
2016             toread[i_stream].i_posf =
2017                 p_stream->p_index[p_stream->i_idxposc].i_pos;
2018             if( p_stream->i_idxposb > 0 )
2019             {
2020                 toread[i_stream].i_posf += 8 + p_stream->i_idxposb;
2021             }
2022
2023         }
2024         else
2025         {
2026             toread[i_stream].i_posf = -1;
2027         }
2028
2029         b_stream = VLC_TRUE; // at least one read succeed
2030
2031         if( p_stream->p_es && p_stream->p_es->p_decoder_fifo )
2032         {
2033             p_pes->i_dts =
2034                 p_pes->i_pts =
2035                     input_ClockGetTS( p_input,
2036                                       p_input->stream.p_selected_program,
2037                                       p_pes->i_pts * 9/100);
2038
2039             input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
2040         }
2041         else
2042         {
2043             input_DeletePES( p_input->p_method_data, p_pes );
2044         }
2045     }
2046 }
2047
2048
2049 /*****************************************************************************
2050  * AVIDemux_UnSeekable: reads and demuxes data packets for unseekable file
2051  *****************************************************************************
2052  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
2053  *****************************************************************************/
2054 static int AVIDemux_UnSeekable( input_thread_t *p_input )
2055 {
2056     demux_sys_t     *p_avi = p_input->p_demux_data;
2057     avi_stream_t *p_stream_master;
2058     vlc_bool_t b_audio;
2059     unsigned int i_stream;
2060     unsigned int i_packet;
2061
2062     /* *** send audio data to decoder only if rate == DEFAULT_RATE *** */
2063     vlc_mutex_lock( &p_input->stream.stream_lock );
2064     b_audio = p_input->stream.control.i_rate == DEFAULT_RATE;
2065     vlc_mutex_unlock( &p_input->stream.stream_lock );
2066
2067     input_ClockManageRef( p_input,
2068                           p_input->stream.p_selected_program,
2069                           p_avi->i_pcr );
2070     /* *** find master stream for data packet skipping algo *** */
2071     /* *** -> first video, if any, or first audio ES *** */
2072     for( i_stream = 0, p_stream_master = NULL;
2073             i_stream < p_avi->i_streams; i_stream++ )
2074     {
2075 #define p_stream    p_avi->pp_info[i_stream]
2076         if( p_stream->p_es &&
2077             p_stream->p_es->p_decoder_fifo )
2078         {
2079             if( p_stream->i_cat == VIDEO_ES )
2080             {
2081                 p_stream_master = p_stream;
2082                 break;
2083             }
2084             if( p_stream->i_cat == AUDIO_ES && !p_stream_master )
2085             {
2086                 p_stream_master = p_stream;
2087             }
2088         }
2089 #undef p_stream
2090     }
2091     if( !p_stream_master )
2092     {
2093         msg_Warn( p_input, "no more stream selected" );
2094         return( 0 );
2095     }
2096
2097     p_avi->i_pcr = AVI_GetPTS( p_stream_master ) * 9 / 100;
2098
2099     for( i_packet = 0; i_packet < 10; i_packet++)
2100     {
2101 #define p_stream    p_avi->pp_info[avi_pk.i_stream]
2102
2103         avi_packet_t    avi_pk;
2104
2105         if( AVI_PacketGetHeader( p_input, &avi_pk ) )
2106         {
2107             return( 0 );
2108         }
2109 //        AVI_ParseStreamHeader( avi_pk.i_fourcc, &i_stream, &i_cat );
2110
2111         if( avi_pk.i_stream >= p_avi->i_streams ||
2112             ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
2113         {
2114             /* we haven't found an audio or video packet:
2115              *  - we have seek, found first next packet
2116              *  - others packets could be found, skip them
2117              */
2118             switch( avi_pk.i_fourcc )
2119             {
2120                 case AVIFOURCC_JUNK:
2121                 case AVIFOURCC_LIST:
2122                     return( !AVI_PacketNext( p_input ) ? 1 : 0 );
2123                 case AVIFOURCC_idx1:
2124                     return( 0 );    // eof
2125                 default:
2126                     msg_Warn( p_input,
2127                               "seems to have lost position, resync" );
2128                     if( AVI_PacketSearch( p_input ) )
2129                     {
2130                         msg_Err( p_input, "resync failed" );
2131                         return( -1 );
2132                     }
2133             }
2134         }
2135         else
2136         {
2137             /* do will send this packet to decoder ? */
2138             if( ( !b_audio && avi_pk.i_cat == AUDIO_ES )||
2139                 !p_stream->p_es ||
2140                 !p_stream->p_es->p_decoder_fifo )
2141             {
2142                 if( AVI_PacketNext( p_input ) )
2143                 {
2144                     return( 0 );
2145                 }
2146             }
2147             else
2148             {
2149                 /* it's a selected stream, check for time */
2150                 if( __ABS( AVI_GetPTS( p_stream ) -
2151                             AVI_GetPTS( p_stream_master ) )< 600*1000 )
2152                 {
2153                     /* load it and send to decoder */
2154                     pes_packet_t    *p_pes;
2155                     if( AVI_PacketRead( p_input, &avi_pk, &p_pes ) || !p_pes)
2156                     {
2157                         return( -1 );
2158                     }
2159                     p_pes->i_dts =
2160                         p_pes->i_pts =
2161                             input_ClockGetTS( p_input,
2162                                           p_input->stream.p_selected_program,
2163                                           AVI_GetPTS( p_stream ) * 9/100);
2164                     input_DecodePES( p_stream->p_es->p_decoder_fifo, p_pes );
2165                 }
2166                 else
2167                 {
2168                     if( AVI_PacketNext( p_input ) )
2169                     {
2170                         return( 0 );
2171                     }
2172                 }
2173             }
2174
2175             /* *** update stream time position *** */
2176             if( p_stream->i_samplesize )
2177             {
2178                 p_stream->i_idxposb += avi_pk.i_size;
2179             }
2180             else
2181             {
2182                 p_stream->i_idxposc++;
2183             }
2184
2185         }
2186
2187 #undef p_stream
2188     }
2189
2190     return( 1 );
2191 }
2192