avi.c 65.7 KB
Newer Older
1
2
3
4
/*****************************************************************************
 * avi.c : AVI file Stream input module for vlc
 *****************************************************************************
 * Copyright (C) 2001 VideoLAN
Laurent Aimar's avatar
Laurent Aimar committed
5
 * $Id: avi.c,v 1.79 2003/11/28 13:24:52 fenrir Exp $
6
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7
 *
8
9
10
11
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
12
 *
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <stdlib.h>                                      /* malloc(), free() */

#include <vlc/vlc.h>
#include <vlc/input.h>
30
#include "codecs.h"
31

32
#include "libavi.h"
33
34
35
36
37
#include "avi.h"

/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
38
39
40
static int  Open   ( vlc_object_t * );
static void Close  ( vlc_object_t * );

41
vlc_module_begin();
gbazin's avatar
   
gbazin committed
42
    add_category_hint( N_("avi-demuxer"), NULL, VLC_TRUE );
43
        add_bool( "avi-interleaved", 0, NULL,
gbazin's avatar
   
gbazin committed
44
45
                  N_("force interleaved method"),
                  N_("force interleaved method"), VLC_TRUE );
46
        add_bool( "avi-index", 0, NULL,
gbazin's avatar
   
gbazin committed
47
48
                  N_("force index creation"),
                  N_("force index creation"), VLC_TRUE );
49

gbazin's avatar
   
gbazin committed
50
    set_description( N_("AVI demuxer") );
51
    set_capability( "demux", 212 );
52
    set_callbacks( Open, Close );
53
54
vlc_module_end();

55
56
57
/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
58
static int    Control         ( input_thread_t *, int, va_list );
59
60
61
62
63
64
static int    Seek            ( input_thread_t *, mtime_t, int );
static int    Demux_Seekable  ( input_thread_t * );
static int    Demux_UnSeekable( input_thread_t *p_input );

#define FREE( p ) if( p ) { free( p ); (p) = NULL; }
#define __ABS( x ) ( (x) < 0 ? (-(x)) : (x) )
65

66
67
static inline off_t __EVEN( off_t i )
{
68
    return (i & 1) ? i + 1 : i;
69
70
}

71
72
73
74
static mtime_t AVI_PTSToChunk( avi_track_t *, mtime_t i_pts );
static mtime_t AVI_PTSToByte ( avi_track_t *, mtime_t i_pts );
static mtime_t AVI_GetDPTS   ( avi_track_t *, int64_t i_count );
static mtime_t AVI_GetPTS    ( avi_track_t * );
75

76

77
static int AVI_StreamChunkFind( input_thread_t *, unsigned int i_stream );
78
79
80
81
static int AVI_StreamChunkSet ( input_thread_t *,
                                unsigned int i_stream, unsigned int i_ck );
static int AVI_StreamBytesSet ( input_thread_t *,
                                unsigned int i_stream, off_t   i_byte );
82

83
vlc_fourcc_t AVI_FourccGetCodec( unsigned int i_cat, vlc_fourcc_t );
84
static int   AVI_GetKeyFlag    ( vlc_fourcc_t , uint8_t * );
85

86
87
static int AVI_PacketGetHeader( input_thread_t *, avi_packet_t *p_pk );
static int AVI_PacketNext     ( input_thread_t * );
88
static int AVI_PacketRead     ( input_thread_t *, avi_packet_t *, block_t **);
89
static int AVI_PacketSearch   ( input_thread_t * );
90

91
92
static void AVI_IndexLoad    ( input_thread_t * );
static void AVI_IndexCreate  ( input_thread_t * );
93
static void AVI_IndexAddEntry( demux_sys_t *, int, AVIIndexEntry_t * );
94

95
static mtime_t  AVI_MovieGetLength( input_thread_t * );
96

97
98
99
/*****************************************************************************
 * Stream management
 *****************************************************************************/
100
101
static int        AVI_TrackSeek  ( input_thread_t *, int, mtime_t );
static int        AVI_TrackStopFinishedStreams( input_thread_t *);
102

103
104
105
106
107
/*****************************************************************************
 * Open: check file and initializes AVI structures
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
108
109
110
    input_thread_t  *p_input = (input_thread_t *)p_this;
    demux_sys_t     *p_sys;

111
112
113
114
    avi_chunk_t         ck_riff;
    avi_chunk_list_t    *p_riff = (avi_chunk_list_t*)&ck_riff;
    avi_chunk_list_t    *p_hdrl, *p_movi;
    avi_chunk_avih_t    *p_avih;
115
116

    unsigned int i_track;
117
    unsigned int i;
118

119
    uint8_t  *p_peek;
120

121

122
    /* Is it an avi file ? */
123
    if( stream_Peek( p_input->s, &p_peek, 12 ) < 12 )
124
    {
125
126
        msg_Err( p_input, "cannot peek()" );
        return VLC_EGENERIC;
127
    }
128
    if( strncmp( &p_peek[0], "RIFF", 4 ) || strncmp( &p_peek[8], "AVI ", 4 ) )
129
    {
130
131
        msg_Warn( p_input, "avi module discarded (invalid header)" );
        return VLC_EGENERIC;
132
    }
133

134
    /* Initialize input  structures. */
135
136
137
138
139
140
141
142
143
144
145
    p_sys = p_input->p_demux_data = malloc( sizeof(demux_sys_t) );
    memset( p_sys, 0, sizeof( demux_sys_t ) );
    p_sys->i_time   = 0;
    p_sys->i_length = 0;
    p_sys->i_pcr    = 0;
    p_sys->i_movi_lastchunk_pos = 0;
    p_sys->b_odml   = VLC_FALSE;
    p_sys->i_track  = 0;
    p_sys->track    = NULL;

    stream_Control( p_input->s, STREAM_CAN_FASTSEEK, &p_sys->b_seekable );
146

147
    p_input->pf_demux_control = Control;
148
149
    p_input->pf_demux = Demux_Seekable;
    /* For unseekable stream, automaticaly use Demux_UnSeekable */
150
    if( !p_sys->b_seekable || config_GetInt( p_input, "avi-interleaved" ) )
151
    {
152
        p_input->pf_demux = Demux_UnSeekable;
153
    }
154

155
    if( AVI_ChunkReadRoot( p_input->s, &p_sys->ck_root ) )
156
    {
157
        msg_Err( p_input, "avi module discarded (invalid file)" );
158
        return VLC_EGENERIC;
159
    }
160

161
    if( AVI_ChunkCount( &p_sys->ck_root, AVIFOURCC_RIFF ) > 1 )
162
    {
163
        unsigned int i_count =
164
            AVI_ChunkCount( &p_sys->ck_root, AVIFOURCC_RIFF );
165

166
167
168
        msg_Warn( p_input, "multiple riff -> OpenDML ?" );
        for( i = 1; i < i_count; i++ )
        {
169
            avi_chunk_list_t *p_sysx;
170

171
172
            p_sysx = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, i );
            if( p_sysx->i_type == AVIFOURCC_AVIX )
173
174
            {
                msg_Warn( p_input, "detected OpenDML file" );
175
                p_sys->b_odml = VLC_TRUE;
176
177
178
179
                break;
            }
        }
    }
180

181
    p_riff  = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0 );
182
183
    p_hdrl  = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0 );
    p_movi  = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0 );
184

185
    if( !p_hdrl || !p_movi )
186
    {
187
188
        msg_Err( p_input, "avi module discarded (invalid file)" );
        goto error;
189
    }
190

191
    if( !( p_avih = AVI_ChunkFind( p_hdrl, AVIFOURCC_avih, 0 ) ) )
192
    {
193
194
        msg_Err( p_input, "cannot find avih chunk" );
        goto error;
195
    }
196
197
    i_track = AVI_ChunkCount( p_hdrl, AVIFOURCC_strl );
    if( p_avih->i_streams != i_track )
198
    {
199
200
        msg_Warn( p_input,
                  "found %d stream but %d are declared",
201
                  i_track, p_avih->i_streams );
202
    }
203
    if( i_track == 0 )
204
    {
205
206
        msg_Err( p_input, "no stream defined!" );
        goto error;
207
    }
208

209
210
211
    /*  create one program */
    vlc_mutex_lock( &p_input->stream.stream_lock );
    if( input_InitStream( p_input, 0 ) == -1)
212
    {
213
214
215
        vlc_mutex_unlock( &p_input->stream.stream_lock );
        msg_Err( p_input, "cannot init stream" );
        goto error;
216
    }
217
218
    p_input->stream.i_mux_rate = 0; /* Fixed later */
    vlc_mutex_unlock( &p_input->stream.stream_lock );
219

220
221
    /* print informations on streams */
    msg_Dbg( p_input, "AVIH: %d stream, flags %s%s%s%s ",
222
             i_track,
223
224
225
226
227
228
             p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
             p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
             p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
             p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
    {
        input_info_category_t *p_cat = input_InfoCategory( p_input, _("Avi") );
229
        input_AddInfo( p_cat, _("Number of Streams"), "%d", i_track );
230
231
232
233
234
235
        input_AddInfo( p_cat, _("Flags"), "%s%s%s%s",
                       p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
                       p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
                       p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
                       p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
    }
236

237
    /* now read info on each stream and create ES */
238
239
240
    for( i = 0 ; i < i_track; i++ )
    {
        avi_track_t      *tk = malloc( sizeof( avi_track_t ) );
Eric Petit's avatar
Eric Petit committed
241
        avi_chunk_list_t *p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i );
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
        avi_chunk_strh_t *p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0 );
        avi_chunk_strf_auds_t *p_auds;
        avi_chunk_strf_vids_t *p_vids;
        es_format_t fmt;

        tk->b_activated = VLC_FALSE;
        tk->p_index     = 0;
        tk->i_idxnb     = 0;
        tk->i_idxmax    = 0;
        tk->i_idxposc   = 0;
        tk->i_idxposb   = 0;

        p_auds = (void*)p_vids = (void*)AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0 );

        if( p_strl == NULL || p_strh == NULL || p_auds == NULL || p_vids == NULL )
257
        {
258
259
            msg_Warn( p_input, "stream[%d] incomplete", i );
            continue;
260
        }
261

262
263
264
        tk->i_rate  = p_strh->i_rate;
        tk->i_scale = p_strh->i_scale;
        tk->i_samplesize = p_strh->i_samplesize;
265
        msg_Dbg( p_input, "stream[%d] rate:%d scale:%d samplesize:%d",
266
267
268
                 i, tk->i_rate, tk->i_scale, tk->i_samplesize );

        switch( p_strh->i_type )
269
        {
270
            case( AVIFOURCC_auds ):
271
272
273
274
275
276
                tk->i_cat   = AUDIO_ES;
                tk->i_codec = AVI_FourccGetCodec( AUDIO_ES,
                                                  p_auds->p_wf->wFormatTag );
                es_format_Init( &fmt, AUDIO_ES, tk->i_codec );

                fmt.audio.i_channels        = p_auds->p_wf->nChannels;
gbazin's avatar
   
gbazin committed
277
                fmt.audio.i_rate            = p_auds->p_wf->nSamplesPerSec;
gbazin's avatar
   
gbazin committed
278
                fmt.i_bitrate               = p_auds->p_wf->nAvgBytesPerSec*8;
279
280
                fmt.audio.i_blockalign      = p_auds->p_wf->nBlockAlign;
                fmt.audio.i_bitspersample   = p_auds->p_wf->wBitsPerSample;
gbazin's avatar
   
gbazin committed
281
282
283
                fmt.i_extra = __MIN( p_auds->p_wf->cbSize,
                    p_auds->i_chunk_size - sizeof(WAVEFORMATEX) );
                fmt.p_extra = &p_auds->p_wf[1];
284
                msg_Dbg( p_input, "stream[%d] audio(0x%x) %d channels %dHz %dbits",
gbazin's avatar
   
gbazin committed
285
                         i, p_auds->p_wf->wFormatTag, p_auds->p_wf->nChannels,
286
                         p_auds->p_wf->nSamplesPerSec, p_auds->p_wf->wBitsPerSample);
287
288
289
                break;

            case( AVIFOURCC_vids ):
290
291
292
293
294
295
296
                tk->i_cat   = VIDEO_ES;
                tk->i_codec = AVI_FourccGetCodec( VIDEO_ES,
                                                  p_vids->p_bih->biCompression );
                es_format_Init( &fmt, VIDEO_ES, p_vids->p_bih->biCompression );
                tk->i_samplesize = 0;
                fmt.video.i_width  = p_vids->p_bih->biWidth;
                fmt.video.i_height = p_vids->p_bih->biHeight;
gbazin's avatar
   
gbazin committed
297
298
299
300
                fmt.i_extra =
                    __MIN( p_vids->p_bih->biSize - sizeof( BITMAPINFOHEADER ),
                           p_vids->i_chunk_size - sizeof(BITMAPINFOHEADER) );
                fmt.p_extra = &p_vids->p_bih[1];
301
302
                msg_Dbg( p_input, "stream[%d] video(%4.4s) %dx%d %dbpp %ffps",
                        i,
303
304
305
306
307
                         (char*)&p_vids->p_bih->biCompression,
                         p_vids->p_bih->biWidth,
                         p_vids->p_bih->biHeight,
                         p_vids->p_bih->biBitCount,
                         (float)tk->i_rate/(float)tk->i_scale );
308
309
310
                break;
            default:
                msg_Warn( p_input, "stream[%d] unknown type", i );
311
312
                free( tk );
                continue;
313
        }
314
315
316
317
318
319
320
321
        tk->p_es = es_out_Add( p_input->p_es_out, &fmt );
        TAB_APPEND( p_sys->i_track, p_sys->track, tk );
    }

    if( p_sys->i_track <= 0 )
    {
        msg_Err( p_input, "No valid track" );
        goto error;
322
323
    }

324
    if( config_GetInt( p_input, "avi-index" ) )
325
    {
326
        if( p_sys->b_seekable )
327
        {
328
            AVI_IndexCreate( p_input );
329
        }
330
        else
331
        {
332
333
            msg_Warn( p_input, "cannot create index (unseekable stream)" );
            AVI_IndexLoad( p_input );
334
335
        }
    }
336
    else
337
    {
338
        AVI_IndexLoad( p_input );
339
    }
340
341

    /* *** movie length in sec *** */
342
343
    p_sys->i_length = AVI_MovieGetLength( p_input );
    if( p_sys->i_length < (mtime_t)p_avih->i_totalframes *
344
345
                          (mtime_t)p_avih->i_microsecperframe /
                          (mtime_t)1000000 )
346
    {
347
        msg_Warn( p_input, "broken or missing index, 'seek' will be axproximative or will have strange behavour" );
348
    }
349
    /* fix some BeOS MediaKit generated file */
350
    for( i = 0 ; i < p_sys->i_track; i++ )
351
    {
352
353
354
355
        avi_track_t         *tk = p_sys->track[i];
        avi_chunk_list_t    *p_strl;
        avi_chunk_strh_t    *p_strh;
        avi_chunk_strf_auds_t    *p_auds;
356

357
        if( tk->i_cat != AUDIO_ES )
358
359
360
        {
            continue;
        }
361
362
363
        if( tk->i_idxnb < 1 ||
            tk->i_scale != 1 ||
            tk->i_samplesize != 0 )
364
365
366
        {
            continue;
        }
367
368
369
        p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i );
        p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0 );
        p_auds = AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0 );
370

371
372
        if( p_auds->p_wf->wFormatTag != WAVE_FORMAT_PCM &&
            (unsigned int)tk->i_rate == p_auds->p_wf->nSamplesPerSec )
373
374
        {
            int64_t i_track_length =
375
376
                tk->p_index[tk->i_idxnb-1].i_length +
                tk->p_index[tk->i_idxnb-1].i_lengthtotal;
377
378
            mtime_t i_length = (mtime_t)p_avih->i_totalframes *
                               (mtime_t)p_avih->i_microsecperframe;
379

380
381
382
383
384
            if( i_length == 0 )
            {
                msg_Warn( p_input, "track[%d] cannot be fixed (BeOS MediaKit generated)", i );
                continue;
            }
385
386
387
            tk->i_samplesize = 1;
            tk->i_rate       = i_track_length  * (int64_t)1000000/ i_length;
            msg_Warn( p_input, "track[%d] fixed with rate=%d scale=%d (BeOS MediaKit generated)", i, tk->i_rate, tk->i_scale );
388
389
        }
    }
390

391
    if( p_sys->i_length )
392
    {
393
        p_input->stream.i_mux_rate =
394
            stream_Size( p_input->s ) / 50 / p_sys->i_length;
395
    }
396

397
    if( p_sys->b_seekable )
398
399
    {
        /* we have read all chunk so go back to movi */
400
        stream_Seek( p_input->s, p_movi->i_chunk_pos );
401
    }
402
    /* Skip movi header */
403
    stream_Read( p_input->s, NULL, 12 );
404

405
    p_sys->i_movi_begin = p_movi->i_chunk_pos;
406
    return VLC_SUCCESS;
407
408

error:
409
410
    AVI_ChunkFreeRoot( p_input->s, &p_sys->ck_root );
    free( p_sys );
411
    return VLC_EGENERIC;
412
413
}

414
415
416
417
/*****************************************************************************
 * Close: frees unused data
 *****************************************************************************/
static void Close ( vlc_object_t * p_this )
418
{
419
420
    input_thread_t *    p_input = (input_thread_t *)p_this;
    unsigned int i;
421
    demux_sys_t *p_sys = p_input->p_demux_data  ;
422

423
    for( i = 0; i < p_sys->i_track; i++ )
424
    {
425
        if( p_sys->track[i] )
426
        {
427
428
            FREE( p_sys->track[i]->p_index );
            free( p_sys->track[i] );
429
430
        }
    }
431
432
    FREE( p_sys->track );
    AVI_ChunkFreeRoot( p_input->s, &p_sys->ck_root );
433

434
    free( p_sys );
435
436
}

437
438
439
440
441
442
443
/*****************************************************************************
 * Demux_Seekable: reads and demuxes data packets for stream seekable
 *****************************************************************************
 * AVIDemux: reads and demuxes data packets
 *****************************************************************************
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
 *****************************************************************************/
444
typedef struct
445
{
446
    vlc_bool_t b_ok;
447

448
    int i_toread;
449

hartman's avatar
hartman committed
450
451
452
    off_t i_posf; /* where we will read :
                   if i_idxposb == 0 : begining of chunk (+8 to acces data)
                   else : point on data directly */
453
} avi_track_toread_t;
454

455
456
static int Demux_Seekable( input_thread_t *p_input )
{
457
458
459
460
    demux_sys_t *p_sys = p_input->p_demux_data;

    unsigned int i_track_count = 0;
    unsigned int i_track;
461
    vlc_bool_t b_stream;
hartman's avatar
hartman committed
462
    /* cannot be more than 100 stream (dcXX or wbXX) */
463
    avi_track_toread_t toread[100];
464
465


466
    /* detect new selected/unselected streams */
467
    for( i_track = 0; i_track < p_sys->i_track; i_track++ )
468
    {
469
470
471
        avi_track_t *tk = p_sys->track[i_track];
        vlc_bool_t  b;

472
        es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
473
        if( b && !tk->b_activated )
474
        {
475
            if( p_sys->b_seekable)
476
            {
477
                AVI_TrackSeek( p_input, i_track, p_sys->i_time );
478
            }
479
            tk->b_activated = VLC_TRUE;
480
        }
481
        else if( !b && tk->b_activated )
482
        {
483
484
485
486
487
            tk->b_activated = VLC_FALSE;
        }
        if( b )
        {
            i_track_count++;
488
489
490
        }
    }

491
    if( i_track_count <= 0 )
492
    {
493
494
        msg_Warn( p_input, "no track selected, exiting..." );
        return( 0 );
495
    }
496

497
    /* wait for the good time */
498
    p_sys->i_pcr = p_sys->i_time * 9 / 100;
499

500
501
    input_ClockManageRef( p_input,
                          p_input->stream.p_selected_program,
502
                          p_sys->i_pcr );
503

504

505
    p_sys->i_time += 25*1000;  /* read 25ms */
506
507

    /* init toread */
508
    for( i_track = 0; i_track < p_sys->i_track; i_track++ )
509
    {
510
        avi_track_t *tk = p_sys->track[i_track];
511
        mtime_t i_dpts;
512

513
514
        toread[i_track].b_ok = tk->b_activated;
        if( tk->i_idxposc < tk->i_idxnb )
515
        {
516
517
            toread[i_track].i_posf = tk->p_index[tk->i_idxposc].i_pos;
           if( tk->i_idxposb > 0 )
518
           {
519
                toread[i_track].i_posf += 8 + tk->i_idxposb;
520
           }
521
        }
522
        else
523
        {
524
            toread[i_track].i_posf = -1;
525
526
        }

527
        i_dpts = p_sys->i_time - AVI_GetPTS( tk  );
528

529
        if( tk->i_samplesize )
530
        {
531
            toread[i_track].i_toread = AVI_PTSToByte( tk, __ABS( i_dpts ) );
532
533
534
        }
        else
        {
535
            toread[i_track].i_toread = AVI_PTSToChunk( tk, __ABS( i_dpts ) );
536
        }
537

538
        if( i_dpts < 0 )
539
        {
540
            toread[i_track].i_toread *= -1;
541
        }
542
543
    }

544
    b_stream = VLC_FALSE;
545

546
    for( ;; )
547
    {
548
        avi_track_t     *tk;
549
        vlc_bool_t       b_done;
550
        block_t         *p_frame;
551
552
553
        off_t i_pos;
        unsigned int i;
        size_t i_size;
554

555
        /* search for first chunk to be read */
556
        for( i = 0, b_done = VLC_TRUE, i_pos = -1; i < p_sys->i_track; i++ )
557
558
        {
            if( !toread[i].b_ok ||
559
                AVI_GetDPTS( p_sys->track[i],
560
561
562
563
                             toread[i].i_toread ) <= -25 * 1000 )
            {
                continue;
            }
564

565
566
            if( toread[i].i_toread > 0 )
            {
hartman's avatar
hartman committed
567
                b_done = VLC_FALSE; /* not yet finished */
568
569
570
            }
            if( toread[i].i_posf > 0 )
            {
571
                if( i_pos == -1 || i_pos > toread[i_track].i_posf )
572
                {
573
                    i_track = i;
574
575
576
                    i_pos = toread[i].i_posf;
                }
            }
577
        }
578

579
        if( b_done )
580
        {
581
            return( 1 );
582
        }
583

584
        if( i_pos == -1 )
585
        {
586
587
            /* no valid index, we will parse directly the stream
             * in case we fail we will disable all finished stream */
588
            if( p_sys->i_movi_lastchunk_pos >= p_sys->i_movi_begin + 12 )
589
            {
590
                stream_Seek( p_input->s, p_sys->i_movi_lastchunk_pos );
591
592
                if( AVI_PacketNext( p_input ) )
                {
593
                    return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 );
594
595
596
597
                }
            }
            else
            {
598
                stream_Seek( p_input->s, p_sys->i_movi_begin + 12 );
599
600
601
602
603
604
605
606
607
608
            }

            for( ;; )
            {
                avi_packet_t avi_pk;

                if( AVI_PacketGetHeader( p_input, &avi_pk ) )
                {
                    msg_Warn( p_input,
                             "cannot get packet header, track disabled" );
609
                    return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 );
610
                }
611
                if( avi_pk.i_stream >= p_sys->i_track ||
612
613
614
615
616
617
                    ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
                {
                    if( AVI_PacketNext( p_input ) )
                    {
                        msg_Warn( p_input,
                                  "cannot skip packet, track disabled" );
618
                        return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 );
619
620
621
622
623
624
625
626
627
628
                    }
                    continue;
                }
                else
                {
                    /* add this chunk to the index */
                    AVIIndexEntry_t index;

                    index.i_id = avi_pk.i_fourcc;
                    index.i_flags =
629
                       AVI_GetKeyFlag(p_sys->track[avi_pk.i_stream]->i_codec,
630
631
632
                                      avi_pk.i_peek);
                    index.i_pos = avi_pk.i_pos;
                    index.i_length = avi_pk.i_size;
633
                    AVI_IndexAddEntry( p_sys, avi_pk.i_stream, &index );
634

635
                    i_track = avi_pk.i_stream;
636
                    tk = p_sys->track[i_track];
637
                    /* do we will read this data ? */
638
                    if( AVI_GetDPTS( tk, toread[i_track].i_toread ) > -25*1000 )
639
640
641
642
643
644
645
646
647
                    {
                        break;
                    }
                    else
                    {
                        if( AVI_PacketNext( p_input ) )
                        {
                            msg_Warn( p_input,
                                      "cannot skip packet, track disabled" );
648
                            return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 );
649
650
651
652
653
                        }
                    }
                }
            }

654
        }
655
656
        else
        {
657
            stream_Seek( p_input->s, i_pos );
658
659
        }

660
661
662
        /* Set the track to use */
        tk = p_sys->track[i_track];

663
        /* read thoses data */
664
        if( tk->i_samplesize )
665
        {
666
667
            unsigned int i_toread;

668
            if( ( i_toread = toread[i_track].i_toread ) <= 0 )
669
            {
670
                if( tk->i_samplesize > 1 )
671
                {
672
                    i_toread = tk->i_samplesize;
673
674
                }
                else
675
                {
676
                    i_toread = __MAX( AVI_PTSToByte( tk, 20 * 1000 ), 100 );
677
678
                }
            }
679
680
            i_size = __MIN( tk->p_index[tk->i_idxposc].i_length -
                                tk->i_idxposb,
681
682
683
684
                            i_toread );
        }
        else
        {
685
            i_size = tk->p_index[tk->i_idxposc].i_length;
686
687
        }

688
        if( tk->i_idxposb == 0 )
689
        {
hartman's avatar
hartman committed
690
            i_size += 8; /* need to read and skip header */
691
        }
692

693
        if( ( p_frame = stream_Block( p_input->s, __EVEN( i_size ) ) )==NULL )
694
695
        {
            msg_Warn( p_input, "failled reading data" );
696
697
            tk->b_activated = VLC_FALSE;
            toread[i_track].b_ok = VLC_FALSE;
698
699
            continue;
        }
hartman's avatar
hartman committed
700
        if( i_size % 2 )    /* read was padded on word boundary */
701
        {
702
            p_frame->i_buffer--;
703
        }
hartman's avatar
hartman committed
704
        /* skip header */
705
        if( tk->i_idxposb == 0 )
706
        {
707
708
            p_frame->p_buffer += 8;
            p_frame->i_buffer -= 8;
709
        }
710
        p_frame->i_pts = AVI_GetPTS( tk );
711

712
        /* read data */
713
        if( tk->i_samplesize )
714
        {
715
            if( tk->i_idxposb == 0 )
716
717
718
            {
                i_size -= 8;
            }
719
720
721
722
            toread[i_track].i_toread -= i_size;
            tk->i_idxposb += i_size;
            if( tk->i_idxposb >=
                    tk->p_index[tk->i_idxposc].i_length )
723
            {
724
725
                tk->i_idxposb = 0;
                tk->i_idxposc++;
726
727
728
729
            }
        }
        else
        {
730
731
            toread[i_track].i_toread--;
            tk->i_idxposc++;
732
        }
733

734
        if( tk->i_idxposc < tk->i_idxnb)
735
        {
736
737
738
            toread[i_track].i_posf =
                tk->p_index[tk->i_idxposc].i_pos;
            if( tk->i_idxposb > 0 )
739
            {
740
                toread[i_track].i_posf += 8 + tk->i_idxposb;
741
            }
742

743
744
745
        }
        else
        {
746
            toread[i_track].i_posf = -1;
747
        }
748

hartman's avatar
hartman committed
749
        b_stream = VLC_TRUE; /* at least one read succeed */
750

751
        p_frame->i_pts =
752
753
            input_ClockGetTS( p_input,
                              p_input->stream.p_selected_program,
754
                              p_frame->i_pts * 9/100);
gbazin's avatar
   
gbazin committed
755
756
757

        if( tk->i_cat != VIDEO_ES )
            p_frame->i_dts = p_frame->i_pts;
758
759
        else
        {
gbazin's avatar
   
gbazin committed
760
761
            p_frame->i_dts = p_frame->i_pts;
            p_frame->i_pts = 0;
762
        }
gbazin's avatar
   
gbazin committed
763
764
765

        //p_pes->i_rate = p_input->stream.control.i_rate;
        es_out_Send( p_input->p_es_out, tk->p_es, p_frame );
766
    }
767
}
768

769

770
771
772
773
774
775
776
/*****************************************************************************
 * Demux_UnSeekable: reads and demuxes data packets for unseekable file
 *****************************************************************************
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
 *****************************************************************************/
static int Demux_UnSeekable( input_thread_t *p_input )
{
777
778
    demux_sys_t     *p_sys = p_input->p_demux_data;
    avi_track_t *p_stream_master = NULL;
779
780
781
    vlc_bool_t b_audio;
    unsigned int i_stream;
    unsigned int i_packet;
782

783
784
    /* Check if we need to send the audio data to decoder */
    b_audio = !p_input->stream.control.b_mute;
785

786
787
    input_ClockManageRef( p_input,
                          p_input->stream.p_selected_program,
788
789
                          p_sys->i_pcr );

790
791
    /* *** find master stream for data packet skipping algo *** */
    /* *** -> first video, if any, or first audio ES *** */
792
    for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
793
    {
794
795
796
        avi_track_t *tk = p_sys->track[i_stream];
        vlc_bool_t  b;

797
        es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
798
799

        if( b && tk->i_cat == VIDEO_ES )
800
        {
801
802
803
804
805
            p_stream_master = tk;
        }
        else if( b )
        {
            p_stream_master = tk;
806
        }
807
    }
808