avi.c 80.9 KB
Newer Older
1
2
3
4
/*****************************************************************************
 * avi.c : AVI file Stream input module for vlc
 *****************************************************************************
 * Copyright (C) 2001 VideoLAN
5
 * $Id: avi.c,v 1.53 2003/07/20 12:34:36 sigmunau 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
30
31
32
33
 * 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 <string.h>                                              /* strdup() */
#include <errno.h>
#include <sys/types.h>

#include <vlc/vlc.h>
#include <vlc/input.h>

Sam Hocevar's avatar
Sam Hocevar committed
34
#include "vlc_video.h"
35

36
#include "libavi.h"
37
38
39
40
41
42

#define __AVI_SUBTITLE__ 1

#ifdef __AVI_SUBTITLE__
#   include "../util/sub.h"
#endif
43
44
45
46
47
48
49
#include "avi.h"

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
static int    AVIInit   ( vlc_object_t * );
static void __AVIEnd    ( vlc_object_t * );
50
51
52
static int    AVISeek   ( input_thread_t *, mtime_t, int );
static int    AVIDemux_Seekable  ( input_thread_t * );
static int    AVIDemux_UnSeekable( input_thread_t *p_input );
53
54

#define AVIEnd(a) __AVIEnd(VLC_OBJECT(a))
55
#define FREE( p ) if( p ) { free( p ); (p) = NULL; }
56
57
58
59
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
vlc_module_begin();
gbazin's avatar
   
gbazin committed
60
    add_category_hint( N_("avi-demuxer"), NULL, VLC_TRUE );
61
        add_bool( "avi-interleaved", 0, NULL,
gbazin's avatar
   
gbazin committed
62
63
                  N_("force interleaved method"),
                  N_("force interleaved method"), VLC_TRUE );
64
        add_bool( "avi-index", 0, NULL,
gbazin's avatar
   
gbazin committed
65
66
                  N_("force index creation"),
                  N_("force index creation"), VLC_TRUE );
67

gbazin's avatar
   
gbazin committed
68
    set_description( N_("AVI demuxer") );
69
    set_capability( "demux", 212 );
70
71
72
73
    set_callbacks( AVIInit, __AVIEnd );
vlc_module_end();

/*****************************************************************************
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
85
    return (uint32_t)p_buff[0] | ( ((uint32_t)p_buff[1]) << 8 ) |
            ( ((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
91
    return (uint32_t)p_buff[3] | ( ((uint32_t)p_buff[2]) << 8 ) |
            ( ((uint32_t)p_buff[1]) << 16 ) | ( ((uint32_t)p_buff[0]) << 24 );
92
}
93
94
static vlc_fourcc_t GetFOURCC( byte_t *p_buff )
{
95
    return VLC_FOURCC( p_buff[0], p_buff[1], p_buff[2], p_buff[3] );
96
97
}

98
99
static inline off_t __EVEN( off_t i )
{
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
107
108
static int input_ReadInPES( input_thread_t *p_input,
                            pes_packet_t **pp_pes,
                            size_t i_size )
109
110
111
112
{
    pes_packet_t *p_pes;
    data_packet_t *p_data;

113

114
115
116
    if( !(p_pes = input_NewPES( p_input->p_method_data ) ) )
    {
        pp_pes = NULL;
117
        return -1;
118
119
120
121
122
123
    }

    *pp_pes = p_pes;

    if( !i_size )
    {
124
125
        p_pes->p_first =
            p_pes->p_last  =
126
127
128
                input_NewPacket( p_input->p_method_data, 0 );
        p_pes->i_nb_data = 1;
        p_pes->i_pes_size = 0;
129
        return 0;
130
    }
131

132
133
134
135
136
137
138
    p_pes->i_nb_data = 0;
    p_pes->i_pes_size = 0;

    while( p_pes->i_pes_size < i_size )
    {
        int i_read;

139
140
141
        i_read = input_SplitBuffer(p_input,
                                   &p_data,
                                   __MIN( i_size -
142
                                          p_pes->i_pes_size, 2048 ) );
143
144
        if( i_read <= 0 )
        {
145
146
147
148
149
            /* should occur only with EOF and max allocation reached 
             * it safer to  return an error */
            /* free pes */
            input_DeletePES( p_input->p_method_data, p_pes );
            return -1;
150
        }
151

152
153
154
155
156
157
158
159
160
161
162
        if( !p_pes->p_first )
        {
            p_pes->p_first = p_data;
        }
        else
        {
            p_pes->p_last->p_next = p_data;
        }
        p_pes->p_last = p_data;
        p_pes->i_nb_data++;
        p_pes->i_pes_size += i_read;
163
    }
164
165


166
    return p_pes->i_pes_size;
167
168
}

169
170
171
/* check if the file is interleaved */
static vlc_bool_t AVI_Interleaved( input_thread_t *p_input );

172
/* Test if it seems that it's a key frame */
173
static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, uint8_t *p_byte )
174
175
176
177
{
    switch( i_fourcc )
    {
        case FOURCC_DIV1:
178
            /* we have:
179
180
181
             *  startcode:      0x00000100   32bits
             *  framenumber     ?             5bits
             *  piture type     0(I),1(P)     2bits
182
             */
183
            if( GetDWBE( p_byte ) != 0x00000100 )
184
            {
185
186
                /* it's not an msmpegv1 stream, strange...*/
                return AVIIF_KEYFRAME;
187
188
189
            }
            else
            {
190
                return p_byte[4] & 0x06 ? 0 : AVIIF_KEYFRAME;
191
192
            }
        case FOURCC_DIV2:
193
194
        case FOURCC_DIV3:   // wmv1 also
            /* we have
195
             *  picture type    0(I),1(P)     2bits
196
             */
197
            return p_byte[0] & 0xC0 ? 0 : AVIIF_KEYFRAME;
198
        case FOURCC_mp4v:
199
            /* we should find first occurence of 0x000001b6 (32bits)
200
201
202
             *  startcode:      0x000001b6   32bits
             *  piture type     0(I),1(P)     2bits
             */
203
204
            if( GetDWBE( p_byte ) != 0x000001b6 )
            {
205
                /* not true , need to find the first VOP header */
206
                return AVIIF_KEYFRAME;
207
208
209
            }
            else
            {
210
                return p_byte[4] & 0xC0 ? 0 : AVIIF_KEYFRAME;
211
212
            }
        default:
213
214
            /* I can't do it, so say yes */
            return AVIIF_KEYFRAME;
215
    }
216
}
217

218
vlc_fourcc_t AVI_FourccGetCodec( unsigned int i_cat, vlc_fourcc_t i_codec )
219
220
221
{
    switch( i_cat )
    {
222
        case AUDIO_ES:
223
224
            switch( i_codec )
            {
225
226
227
228
229
230
231
232
233
234
235
                case WAVE_FORMAT_PCM:
                    return VLC_FOURCC( 'a', 'r', 'a', 'w' );
                case WAVE_FORMAT_MPEG:
                case WAVE_FORMAT_MPEGLAYER3:
                    return VLC_FOURCC( 'm', 'p', 'g', 'a' );
                case WAVE_FORMAT_A52:
                    return VLC_FOURCC( 'a', '5', '2', ' ' );
                case WAVE_FORMAT_WMA1:
                    return VLC_FOURCC( 'w', 'm', 'a', '1' );
                case WAVE_FORMAT_WMA2:
                    return VLC_FOURCC( 'w', 'm', 'a', '2' );
236
                default:
237
                    return VLC_FOURCC( 'm', 's',
238
                                       ( i_codec >> 8 )&0xff, i_codec&0xff );
239
            }
240
        case VIDEO_ES:
241
            // XXX DIV1 <- msmpeg4v1, DIV2 <- msmpeg4v2, DIV3 <- msmpeg4v3, mp4v for mpeg4
242
243
244
245
246
247
            switch( i_codec )
            {
                case FOURCC_DIV1:
                case FOURCC_div1:
                case FOURCC_MPG4:
                case FOURCC_mpg4:
248
                    return FOURCC_DIV1;
249
250
251
252
253
254
                case FOURCC_DIV2:
                case FOURCC_div2:
                case FOURCC_MP42:
                case FOURCC_mp42:
                case FOURCC_MPG3:
                case FOURCC_mpg3:
255
                    return FOURCC_DIV2;
256
257
258
259
260
261
262
263
264
265
266
267
                case FOURCC_div3:
                case FOURCC_MP43:
                case FOURCC_mp43:
                case FOURCC_DIV3:
                case FOURCC_DIV4:
                case FOURCC_div4:
                case FOURCC_DIV5:
                case FOURCC_div5:
                case FOURCC_DIV6:
                case FOURCC_div6:
                case FOURCC_AP41:
                case FOURCC_3IV1:
268
269
270
271
272
                case FOURCC_3iv1:
                case FOURCC_3IVD:
                case FOURCC_3ivd:
                case FOURCC_3VID:
                case FOURCC_3vid:
273
                    return FOURCC_DIV3;
274
275
276
277
278
279
280
281
282
283
284
285
                case FOURCC_DIVX:
                case FOURCC_divx:
                case FOURCC_MP4S:
                case FOURCC_mp4s:
                case FOURCC_M4S2:
                case FOURCC_m4s2:
                case FOURCC_xvid:
                case FOURCC_XVID:
                case FOURCC_XviD:
                case FOURCC_DX50:
                case FOURCC_mp4v:
                case FOURCC_4:
286
287
                case FOURCC_3IV2:
                case FOURCC_3iv2:
288
                    return FOURCC_mp4v;
289
290
            }
        default:
291
            return VLC_FOURCC( 'u', 'n', 'd', 'f' );
292
    }
293
294
}

295
296
static void AVI_ParseStreamHeader( vlc_fourcc_t i_id,
                                   int *pi_number, int *pi_type )
297
{
298
#define SET_PTR( p, v ) if( p ) *(p) = (v);
299
300
301
302
    int c1, c2;

    c1 = ((uint8_t *)&i_id)[0];
    c2 = ((uint8_t *)&i_id)[1];
303
304
305

    if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
    {
306
307
        SET_PTR( pi_number, 100 ); /* > max stream number */
        SET_PTR( pi_type, UNKNOWN_ES );
308
309
310
311
    }
    else
    {
        SET_PTR( pi_number, (c1 - '0') * 10 + (c2 - '0' ) );
312
        switch( VLC_TWOCC( ((uint8_t *)&i_id)[2], ((uint8_t *)&i_id)[3] ) )
313
        {
314
            case AVITWOCC_wb:
315
316
                SET_PTR( pi_type, AUDIO_ES );
                break;
317
318
319
            case AVITWOCC_dc:
            case AVITWOCC_db:
                SET_PTR( pi_type, VIDEO_ES );
320
                break;
321
            default:
322
323
324
325
326
327
328
329
330
                SET_PTR( pi_type, UNKNOWN_ES );
                break;
        }
    }
#undef SET_PTR
}

static int AVI_PacketGetHeader( input_thread_t *p_input, avi_packet_t *p_pk )
{
331
    uint8_t  *p_peek;
332

333
334
    if( input_Peek( p_input, &p_peek, 16 ) < 16 )
    {
335
        return VLC_EGENERIC;
336
    }
337
    p_pk->i_fourcc  = GetFOURCC( p_peek );
338
339
    p_pk->i_size    = GetDWLE( p_peek + 4 );
    p_pk->i_pos     = AVI_TellAbsolute( p_input );
340
    if( p_pk->i_fourcc == AVIFOURCC_LIST || p_pk->i_fourcc == AVIFOURCC_RIFF )
341
    {
342
        p_pk->i_type = GetFOURCC( p_peek + 8 );
343
344
345
    }
    else
    {
346
        p_pk->i_type = 0;
347
    }
348

349
350
351
    memcpy( p_pk->i_peek, p_peek + 8, 8 );

    AVI_ParseStreamHeader( p_pk->i_fourcc, &p_pk->i_stream, &p_pk->i_cat );
352
    return VLC_SUCCESS;
353
354
}

355
static int AVI_PacketNext( input_thread_t *p_input )
356
{
357
    avi_packet_t    avi_ck;
358

359
    if( AVI_PacketGetHeader( p_input, &avi_ck ) )
360
    {
361
        return VLC_EGENERIC;
362
    }
363
    //msg_Dbg( p_input, "skip %4.4s:%4.4s", (char*)&avi_ck.i_fourcc, (char*)&avi_ck.i_type );
364

365
    if( avi_ck.i_fourcc == AVIFOURCC_LIST && ( avi_ck.i_type == AVIFOURCC_rec || avi_ck.i_type == AVIFOURCC_movi ) )
366
    {
367
        return AVI_SkipBytes( p_input, 12 );
368
    }
369
370
371
372
    else if( avi_ck.i_fourcc == AVIFOURCC_RIFF && avi_ck.i_type == AVIFOURCC_AVIX )
    {
        return AVI_SkipBytes( p_input, 24 );
    }
373
374
    else
    {
375
        return AVI_SkipBytes( p_input, __EVEN( avi_ck.i_size ) + 8 );
376
    }
377
}
378
379
380
static int AVI_PacketRead( input_thread_t   *p_input,
                           avi_packet_t     *p_pk,
                           pes_packet_t     **pp_pes )
381
{
382
    size_t i_size;
383
    vlc_bool_t b_pad;
384

385
386
    i_size = __EVEN( p_pk->i_size + 8 );
    b_pad  = ( i_size != p_pk->i_size + 8 );
387
388

    if( input_ReadInPES( p_input, pp_pes, i_size ) != (ssize_t)i_size )
389
    {
390
        return VLC_EGENERIC;
391
    }
392
393
    (*pp_pes)->p_first->p_payload_start += 8;
    (*pp_pes)->i_pes_size -= 8;
394
395
396
397
398
399
400

    if( b_pad )
    {
        (*pp_pes)->p_last->p_payload_end--;
        (*pp_pes)->i_pes_size--;
    }

401
    return VLC_SUCCESS;
402
403
}

404
405
406
407
408
409
410
static int AVI_PacketSearch( input_thread_t *p_input )
{
    demux_sys_t     *p_avi = p_input->p_demux_data;

    avi_packet_t    avi_pk;
    for( ;; )
    {
411
        if( AVI_SkipBytes( p_input, 1 ) )
412
        {
413
            return VLC_EGENERIC;
414
415
416
417
418
        }
        AVI_PacketGetHeader( p_input, &avi_pk );
        if( avi_pk.i_stream < p_avi->i_streams &&
            ( avi_pk.i_cat == AUDIO_ES || avi_pk.i_cat == VIDEO_ES ) )
        {
419
            return VLC_SUCCESS;
420
421
422
423
424
        }
        switch( avi_pk.i_fourcc )
        {
            case AVIFOURCC_JUNK:
            case AVIFOURCC_LIST:
425
            case AVIFOURCC_RIFF:
426
            case AVIFOURCC_idx1:
427
                return VLC_SUCCESS;
428
429
430
431
        }
    }
}

432

433
static void __AVI_AddEntryIndex( avi_stream_t *p_info,
434
435
436
437
438
439
                                 AVIIndexEntry_t *p_index)
{
    if( p_info->p_index == NULL )
    {
        p_info->i_idxmax = 16384;
        p_info->i_idxnb = 0;
440
        if( !( p_info->p_index = calloc( p_info->i_idxmax,
441
442
443
444
                                  sizeof( AVIIndexEntry_t ) ) ) )
        {
            return;
        }
445
446
447
448
    }
    if( p_info->i_idxnb >= p_info->i_idxmax )
    {
        p_info->i_idxmax += 16384;
449
        if( !( p_info->p_index = realloc( (void*)p_info->p_index,
450
                           p_info->i_idxmax *
451
452
453
                           sizeof( AVIIndexEntry_t ) ) ) )
        {
            return;
454
455
456
457
458
        }
    }
    /* calculate cumulate length */
    if( p_info->i_idxnb > 0 )
    {
459
        p_index->i_lengthtotal =
460
461
            p_info->p_index[p_info->i_idxnb - 1].i_length +
                p_info->p_index[p_info->i_idxnb - 1].i_lengthtotal;
462
463
464
465
466
467
468
469
    }
    else
    {
        p_index->i_lengthtotal = 0;
    }

    p_info->p_index[p_info->i_idxnb] = *p_index;
    p_info->i_idxnb++;
470
471
472

}

473
474
static void AVI_IndexAddEntry( demux_sys_t *p_avi,
                               int i_stream,
475
476
477
478
479
480
481
482
                               AVIIndexEntry_t *p_index)
{
    __AVI_AddEntryIndex( p_avi->pp_info[i_stream],
                         p_index );
    if( p_avi->i_movi_lastchunk_pos < p_index->i_pos )
    {
        p_avi->i_movi_lastchunk_pos = p_index->i_pos;
    }
483
484
}

485
static int AVI_IndexLoad_idx1( input_thread_t *p_input )
486
{
487
    demux_sys_t *p_avi = p_input->p_demux_data;
488

489
490
491
    avi_chunk_list_t    *p_riff;
    avi_chunk_list_t    *p_movi;
    avi_chunk_idx1_t    *p_idx1;
492

493
494
    unsigned int i_stream;
    unsigned int i_index;
495
    off_t   i_offset;
496
497

    p_riff = (avi_chunk_list_t*)AVI_ChunkFind( &p_avi->ck_root,
498
                                               AVIFOURCC_RIFF, 0);
499

500
501
502
503
    p_idx1 = (avi_chunk_idx1_t*)AVI_ChunkFind( p_riff, AVIFOURCC_idx1, 0);
    p_movi = (avi_chunk_list_t*)AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);

    if( !p_idx1 )
504
    {
505
        msg_Warn( p_input, "cannot find idx1 chunk, no index defined" );
506
        return VLC_EGENERIC;
507
    }
508

509
    /* *** calculate offset *** */
510
    if( p_idx1->i_entry_count > 0 &&
511
512
513
514
515
516
517
518
519
520
        p_idx1->entry[0].i_pos < p_movi->i_chunk_pos )
    {
        i_offset = p_movi->i_chunk_pos + 8;
    }
    else
    {
        i_offset = 0;
    }

    for( i_index = 0; i_index < p_idx1->i_entry_count; i_index++ )
521
    {
522
523
        unsigned int i_cat;

524
525
526
527
528
        AVI_ParseStreamHeader( p_idx1->entry[i_index].i_fourcc,
                               &i_stream,
                               &i_cat );
        if( i_stream < p_avi->i_streams &&
            i_cat == p_avi->pp_info[i_stream]->i_cat )
529
        {
530
531
            AVIIndexEntry_t index;
            index.i_id      = p_idx1->entry[i_index].i_fourcc;
532
            index.i_flags   =
533
                p_idx1->entry[i_index].i_flags&(~AVIIF_FIXKEYFRAME);
534
535
            index.i_pos     = p_idx1->entry[i_index].i_pos + i_offset;
            index.i_length  = p_idx1->entry[i_index].i_length;
536
            AVI_IndexAddEntry( p_avi, i_stream, &index );
537
        }
538
    }
539
    return VLC_SUCCESS;
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
}

static void __Parse_indx( input_thread_t    *p_input,
                          int               i_stream,
                          avi_chunk_indx_t  *p_indx )
{
    demux_sys_t         *p_avi    = p_input->p_demux_data;
    AVIIndexEntry_t     index;
    int32_t             i;

    msg_Dbg( p_input, "loading subindex(0x%x) %d entries", p_indx->i_indextype, p_indx->i_entriesinuse );
    if( p_indx->i_indexsubtype == 0 )
    {
        for( i = 0; i < p_indx->i_entriesinuse; i++ )
        {
            index.i_id      = p_indx->i_id;
            index.i_flags   = p_indx->idx.std[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
            index.i_pos     = p_indx->i_baseoffset + p_indx->idx.std[i].i_offset - 8;
            index.i_length  = p_indx->idx.std[i].i_size&0x7fffffff;

            AVI_IndexAddEntry( p_avi, i_stream, &index );
        }
    }
    else if( p_indx->i_indexsubtype == AVI_INDEX_2FIELD )
    {
        for( i = 0; i < p_indx->i_entriesinuse; i++ )
        {
            index.i_id      = p_indx->i_id;
            index.i_flags   = p_indx->idx.field[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
            index.i_pos     = p_indx->i_baseoffset + p_indx->idx.field[i].i_offset - 8;
            index.i_length  = p_indx->idx.field[i].i_size;

            AVI_IndexAddEntry( p_avi, i_stream, &index );
        }
    }
    else
    {
        msg_Warn( p_input, "unknow subtype index(0x%x)", p_indx->i_indexsubtype );
    }
}

static void AVI_IndexLoad_indx( input_thread_t *p_input )
{
    demux_sys_t         *p_avi = p_input->p_demux_data;
    unsigned int        i_stream;
    int32_t             i;

    avi_chunk_list_t    *p_riff;
    avi_chunk_list_t    *p_hdrl;

    p_riff = (void*)AVI_ChunkFind( &p_avi->ck_root,
                                   AVIFOURCC_RIFF, 0);
    p_hdrl = (void*)AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0 );

    for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
    {
        avi_chunk_list_t    *p_strl;
        avi_chunk_indx_t    *p_indx;

#define p_stream  p_avi->pp_info[i_stream]
        p_strl = (void*)AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i_stream );
        p_indx = (void*)AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0 );

        if( !p_indx )
        {
            msg_Warn( p_input, "cannot find indx (misdetect/broken OpenDML file?)" );
            continue;
        }

        if( p_indx->i_indextype == AVI_INDEX_OF_CHUNKS )
        {
            __Parse_indx( p_input, i_stream, p_indx );
        }
        else if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES )
        {
            avi_chunk_indx_t    ck_sub;
            for( i = 0; i < p_indx->i_entriesinuse; i++ )
            {
618
619
620
621
                if( AVI_SeekAbsolute( p_input, p_indx->idx.super[i].i_offset ) )
                {
                    break;
                }
622

623
                if( AVI_ChunkRead( p_input, &ck_sub, NULL, p_avi->b_seekable ) )
624
                {
625
                    break;
626
627
628
629
630
631
632
633
634
635
                }
            }
        }
        else
        {
            msg_Warn( p_input, "unknow type index(0x%x)", p_indx->i_indextype );
        }
#undef p_stream
    }
}
636

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
static void AVI_IndexLoad( input_thread_t *p_input )
{
    demux_sys_t *p_avi = p_input->p_demux_data;
    unsigned int i_stream;

    for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
    {
        p_avi->pp_info[i_stream]->i_idxnb  = 0;
        p_avi->pp_info[i_stream]->i_idxmax = 0;
        p_avi->pp_info[i_stream]->p_index  = NULL;
    }

    if( p_avi->b_odml )
    {
        AVI_IndexLoad_indx( p_input );
    }
    else
    {
655
656
657
658
659
        if( AVI_IndexLoad_idx1( p_input ) )
        {
            /* try indx if idx1 failed as some "normal" file have indx too */
            AVI_IndexLoad_indx( p_input );
        }
660
661
    }

662
663
    for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
    {
664
        msg_Dbg( p_input,
665
                "stream[%d] created %d index entries",
666
667
668
669
                i_stream,
                p_avi->pp_info[i_stream]->i_idxnb );
    }
}
670

671
672
673
static void AVI_IndexCreate( input_thread_t *p_input )
{
    demux_sys_t *p_avi = p_input->p_demux_data;
674

675
676
677
    avi_chunk_list_t    *p_riff;
    avi_chunk_list_t    *p_movi;

678
679
680
681
    unsigned int i_stream;
    off_t i_movi_end;

    p_riff = (avi_chunk_list_t*)AVI_ChunkFind( &p_avi->ck_root,
682
683
                                               AVIFOURCC_RIFF, 0);
    p_movi = (avi_chunk_list_t*)AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);
684

685
686
687
688
689
690
691
692
693
694
695
696
    if( !p_movi )
    {
        msg_Err( p_input, "cannot find p_movi" );
        return;
    }

    for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
    {
        p_avi->pp_info[i_stream]->i_idxnb  = 0;
        p_avi->pp_info[i_stream]->i_idxmax = 0;
        p_avi->pp_info[i_stream]->p_index  = NULL;
    }
697
    i_movi_end = __MIN( (off_t)(p_movi->i_chunk_pos + p_movi->i_chunk_size),
698
699
700
701
702
703
704
                        p_input->stream.p_selected_area->i_size );

    AVI_SeekAbsolute( p_input, p_movi->i_chunk_pos + 12);
    msg_Warn( p_input, "creating index from LIST-movi, will take time !" );
    for( ;; )
    {
        avi_packet_t pk;
705

706
        if( AVI_PacketGetHeader( p_input, &pk ) )
707
        {
708
709
710
711
712
713
714
            break;
        }
        if( pk.i_stream < p_avi->i_streams &&
            pk.i_cat == p_avi->pp_info[pk.i_stream]->i_cat )
        {
            AVIIndexEntry_t index;
            index.i_id      = pk.i_fourcc;
715
            index.i_flags   =
716
717
718
               AVI_GetKeyFlag(p_avi->pp_info[pk.i_stream]->i_codec, pk.i_peek);
            index.i_pos     = pk.i_pos;
            index.i_length  = pk.i_size;
719
            AVI_IndexAddEntry( p_avi, pk.i_stream, &index );
720
721
722
723
        }
        else
        {
            switch( pk.i_fourcc )
724
            {
725
                case AVIFOURCC_idx1:
726
727
728
729
730
731
732
733
734
735
736
737
738
                    if( p_avi->b_odml )
                    {
                        avi_chunk_list_t *p_avix;
                        p_avix = (void*)AVI_ChunkFind( &p_avi->ck_root,
                                                       AVIFOURCC_RIFF, 1 );

                        msg_Dbg( p_input, "looking for new RIFF chunk" );
                        if( AVI_SeekAbsolute( p_input, p_avix->i_chunk_pos + 24) )
                        {
                            goto print_stat;
                        }
                        break;
                    }
739
                    goto print_stat;
740
741
                case AVIFOURCC_RIFF:
                        msg_Dbg( p_input, "new RIFF chunk found" );
742
743
744
745
746
                case AVIFOURCC_rec:
                case AVIFOURCC_JUNK:
                    break;
                default:
                    msg_Warn( p_input, "need resync, probably broken avi" );
747
                    if( AVI_PacketSearch( p_input ) )
748
749
750
751
                    {
                        msg_Warn( p_input, "lost sync, abord index creation" );
                        goto print_stat;
                    }
752
753
            }
        }
754
755

        if( ( !p_avi->b_odml && pk.i_pos + pk.i_size >= i_movi_end ) ||
756
            AVI_PacketNext( p_input ) )
757
758
759
        {
            break;
        }
760
761
    }

762
763
764
print_stat:
    for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
    {
765
766
        msg_Dbg( p_input,
                "stream[%d] creating %d index entries",
767
768
769
                i_stream,
                p_avi->pp_info[i_stream]->i_idxnb );
    }
770
771
}

772
773

/*****************************************************************************
774
 * Stream management
775
 *****************************************************************************/
776
static vlc_bool_t AVI_StreamStart ( input_thread_t *, demux_sys_t *, int );
777
778
static int  AVI_StreamSeek   ( input_thread_t *, demux_sys_t *, int, mtime_t );
static void AVI_StreamStop   ( input_thread_t *, demux_sys_t *, int );
779
static int  AVI_StreamStopFinishedStreams( input_thread_t *, demux_sys_t * );
780

781
static vlc_bool_t AVI_StreamStart( input_thread_t *p_input,
782
                                   demux_sys_t *p_avi, int i_stream )
783
{
784
785
786
787
#define p_stream    p_avi->pp_info[i_stream]
    if( !p_stream->p_es )
    {
        msg_Warn( p_input, "stream[%d] unselectable", i_stream );
788
        return VLC_FALSE;
789
    }
790
    if( p_stream->b_activated )
791
792
    {
        msg_Warn( p_input, "stream[%d] already selected", i_stream );
793
        return VLC_TRUE;
794
    }
795

796
797
798
799
800
801
    if( !p_stream->p_es->p_decoder_fifo )
    {
        vlc_mutex_lock( &p_input->stream.stream_lock );
        input_SelectES( p_input, p_stream->p_es );
        vlc_mutex_unlock( &p_input->stream.stream_lock );
    }
802
803
    p_stream->b_activated = p_stream->p_es->p_decoder_fifo ? VLC_TRUE
                                                           : VLC_FALSE;
804
    if( p_stream->b_activated && p_avi->b_seekable)
805
806
807
    {
        AVI_StreamSeek( p_input, p_avi, i_stream, p_avi->i_time );
    }
808

809
    return p_stream->b_activated;
810
811
812
813
814
815
816
817
#undef  p_stream
}

static void    AVI_StreamStop( input_thread_t *p_input,
                               demux_sys_t *p_avi, int i_stream )
{
#define p_stream    p_avi->pp_info[i_stream]

818
    if( !p_stream->b_activated )
819
820
821
822
    {
        msg_Warn( p_input, "stream[%d] already unselected", i_stream );
        return;
    }
823

824
825
826
827
828
829
830
    if( p_stream->p_es->p_decoder_fifo )
    {
        vlc_mutex_lock( &p_input->stream.stream_lock );
        input_UnselectES( p_input, p_stream->p_es );
        vlc_mutex_unlock( &p_input->stream.stream_lock );
    }

831

832
    p_stream->b_activated = VLC_FALSE;
833
834
835
836

#undef  p_stream
}

837
838
839
static int AVI_StreamStopFinishedStreams( input_thread_t *p_input,
                                           demux_sys_t *p_avi )
{
Sam Hocevar's avatar
Sam Hocevar committed
840
    unsigned int i_stream;
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
    int b_end;

    for( i_stream = 0,b_end = VLC_TRUE;
            i_stream < p_avi->i_streams; i_stream++ )
    {
#define p_stream    p_avi->pp_info[i_stream]
        if( p_stream->i_idxposc >= p_stream->i_idxnb )
        {
            AVI_StreamStop( p_input, p_avi, i_stream );
        }
        else
        {
            b_end = VLC_FALSE;
        }
#undef  p_stream
    }
    return( b_end );
}
859
860
861
862
863
/****************************************************************************
 * AVI_MovieGetLength give max streams length in second
 ****************************************************************************/
static mtime_t  AVI_MovieGetLength( input_thread_t *p_input, demux_sys_t *p_avi )
{
864
    unsigned int i_stream;
865
    mtime_t i_maxlength;
866

867
    i_maxlength = 0;
868
    for( i_stream = 0; i_stream < p_avi->i_streams; i_stream++ )
869
    {
870
871
872
873
#define p_stream  p_avi->pp_info[i_stream]
        mtime_t i_length;
        /* fix length for each stream */
        if( p_stream->i_idxnb < 1 || !p_stream->p_index )
874
        {
875
            continue;
876
        }
877
878

        if( p_stream->i_samplesize )
879
        {
880
881
            i_length =
                (mtime_t)( p_stream->p_index[p_stream->i_idxnb-1].i_lengthtotal +
882
                           p_stream->p_index[p_stream->i_idxnb-1].i_length ) *
883
884
885
                (mtime_t)p_stream->i_scale /
                (mtime_t)p_stream->i_rate /
                (mtime_t)p_stream->i_samplesize;
886
        }
887
888
889
890
891
892
893
        else
        {
            i_length = (mtime_t)p_stream->i_idxnb *
                       (mtime_t)p_stream->i_scale /
                       (mtime_t)p_stream->i_rate;
        }

894
        msg_Dbg( p_input,
gbazin's avatar
   
gbazin committed
895
                 "stream[%d] length:"I64Fd" (based on index)",
896
897
898
                 i_stream,
                 i_length );
        i_maxlength = __MAX( i_maxlength, i_length );
899
#undef p_stream
900
    }
901

902
    return i_maxlength;
903
904
905
906
907
908
}

/*****************************************************************************
 * AVIEnd: frees unused data
 *****************************************************************************/
static void __AVIEnd ( vlc_object_t * p_this )
909
{
910
    input_thread_t *    p_input = (input_thread_t *)p_this;
911
912
913
    unsigned int i;
    demux_sys_t *p_avi = p_input->p_demux_data  ;

914
915
916
    if( p_avi->pp_info )
    {
        for( i = 0; i < p_avi->i_streams; i++ )
917
        {
918
            if( p_avi->pp_info[i] )
919
            {
920
                if( p_avi->pp_info[i]->p_index )
921
                {
922
                      free( p_avi->pp_info[i]->p_index );
923
                }
924
                free( p_avi->pp_info[i] );
925
926
            }
        }
927
         free( p_avi->pp_info );
928
    }
929
930
931
932
933
934
935
#ifdef __AVI_SUBTITLE__
    if( p_avi->p_sub )
    {
        subtitle_Close( p_avi->p_sub );
        p_avi->p_sub = NULL;
    }
#endif
936
    AVI_ChunkFreeRoot( p_input, &p_avi->ck_root );
937
938

    FREE( p_input->p_demux_data );
939
940
941
942
943
944
}

/*****************************************************************************
 * AVIInit: check file and initializes AVI structures
 *****************************************************************************/
static int AVIInit( vlc_object_t * p_this )
945
{
946
    input_thread_t *    p_input = (input_thread_t *)p_this;
947
948
949
950
951
952
953
954
    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;
#if 0
    avi_chunk_list_t    *p_INFO;
    avi_chunk_strz_t    *p_name;
#endif
    avi_chunk_avih_t    *p_avih;
955
    demux_sys_t *p_avi;
956
    es_descriptor_t *p_es = NULL; /* avoid warning */
957
    unsigned int i;
958
959
960
#ifdef __AVI_SUBTITLE__
    mtime_t i_microsecperframe = 0; // for some subtitle format
#endif
961
962

    vlc_bool_t b_stream_audio, b_stream_video;
963

964
    p_input->pf_demux = AVIDemux_Seekable;
965
    if( AVI_TestFile( p_input ) )
966
    {
967
        msg_Warn( p_input, "avi module discarded (invalid header)" );
968
        return VLC_EGENERIC;
969
970
971
972
973
974
975
976
    }

    /* Initialize access plug-in structures. */
    if( p_input->i_mtu == 0 )
    {
        /* Improve speed. */
        p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
    }
977

978
    if( !( p_input->p_demux_data =
979
                    p_avi = malloc( sizeof(demux_sys_t) ) ) )
980
981
    {
        msg_Err( p_input, "out of memory" );
982
        return VLC_ENOMEM;
983
    }
984
    memset( p_avi, 0, sizeof( demux_sys_t ) );
985
986
    p_avi->i_time = 0;
    p_avi->i_pcr  = 0;
987
    p_avi->b_seekable = ( ( p_input->stream.b_seekable )
988
                        &&( p_input->stream.i_method == INPUT_METHOD_FILE ) );
989
    p_avi->i_movi_lastchunk_pos = 0;
990
    p_avi->b_odml = VLC_FALSE;
991
    p_avi->b_interleaved = VLC_FALSE;
992

993
994
    /* *** for unseekable stream, automaticaly use AVIDemux_interleaved *** */
    if( !p_avi->b_seekable || config_GetInt( p_input, "avi-interleaved" ) )
995
    {
996
        p_input->pf_demux = AVIDemux_UnSeekable;
997
    }
998

999
    if( AVI_ChunkReadRoot( p_input, &p_avi->ck_root, p_avi->b_seekable ) )
1000
    {
1001
        msg_Err( p_input, "avi module discarded (invalid file)" );
1002
        return VLC_EGENERIC;
1003
    }
1004
1005
    AVI_ChunkDumpDebug( p_input, &p_avi->ck_root );

1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
    if( AVI_ChunkCount( &p_avi->ck_root, AVIFOURCC_RIFF ) > 1 )
    {
        int i_count = AVI_ChunkCount( &p_avi->ck_root, AVIFOURCC_RIFF );
        int i;

        msg_Warn( p_input, "multiple riff -> OpenDML ?" );
        for( i = 1; i < i_count; i++ )
        {
            avi_chunk_list_t *p_avix;

            p_avix = (avi_chunk_list_t*)AVI_ChunkFind( &p_avi->ck_root,
                                                       AVIFOURCC_RIFF, i );
            if( p_avix->i_type == AVIFOURCC_AVIX )
            {
                msg_Warn( p_input, "detected OpenDML file" );

                p_avi->b_odml = VLC_TRUE;
                break;
            }
        }
        p_avi->b_odml = VLC_TRUE;
    }

1029

1030
    p_riff  = (avi_chunk_list_t*)AVI_ChunkFind( &p_avi->ck_root,
1031
1032
1033
                                                AVIFOURCC_RIFF, 0 );
    p_hdrl  = (avi_chunk_list_t*)AVI_ChunkFind( p_riff,
                                                AVIFOURCC_hdrl, 0 );
1034
    p_movi  = (avi_chunk_list_t*)AVI_ChunkFind( p_riff,
1035
1036
1037
1038
1039
1040
1041
                                                AVIFOURCC_movi, 0 );
#if 0
    p_INFO  = (avi_chunk_list_t*)AVI_ChunkFind( p_riff,
                                                AVIFOURCC_INFO, 0 );
    p_name  = (avi_chunk_strz_t*)AVI_ChunkFind( p_INFO,
                                                AVIFOURCC_INAM, 0 );
    if( p_name )
1042
    {
1043

1044
    }
1045
#endif
1046