Coverage Report

Created: 2025-07-18 08:04

/src/vlc/modules/demux/avi/avi.c
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************
2
 * avi.c : AVI file Stream input module for vlc
3
 *****************************************************************************
4
 * Copyright (C) 2001-2009 VLC authors and VideoLAN
5
 *
6
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7
 *
8
 * This program is free software; you can redistribute it and/or modify it
9
 * under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program; if not, write to the Free Software Foundation,
20
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21
 *****************************************************************************/
22
23
/*****************************************************************************
24
 * Preamble
25
 *****************************************************************************/
26
27
#ifdef HAVE_CONFIG_H
28
# include "config.h"
29
#endif
30
#include <assert.h>
31
#include <ctype.h>
32
#include <limits.h>
33
34
#include <vlc_common.h>
35
#include <vlc_arrays.h>
36
#include <vlc_plugin.h>
37
#include <vlc_demux.h>
38
#include <vlc_input.h>
39
#include <vlc_aout.h>
40
41
#include <vlc_dialog.h>
42
43
#include <vlc_meta.h>
44
#include <vlc_codecs.h>
45
#include <vlc_charset.h>
46
#include <vlc_arrays.h>
47
48
#include "libavi.h"
49
#include "../rawdv.h"
50
#include "bitmapinfoheader.h"
51
#include "../../packetizer/h264_nal.h"
52
#include "../../packetizer/hevc_nal.h"
53
54
/*****************************************************************************
55
 * Module descriptor
56
 *****************************************************************************/
57
58
#define INTERLEAVE_TEXT N_("Force interleaved method" )
59
60
#define INDEX_TEXT N_("Force index creation")
61
#define INDEX_LONGTEXT N_( \
62
    "Recreate a index for the AVI file. Use this if your AVI file is damaged "\
63
    "or incomplete (not seekable)." )
64
65
static int  Open ( vlc_object_t * );
66
static void Close( vlc_object_t * );
67
68
static const int pi_index[] = {0,1,2,3};
69
70
static const char *const ppsz_indexes[] = { N_("Ask for action"),
71
                                            N_("Always fix"),
72
                                            N_("Never fix"),
73
                                            N_("Fix when necessary")};
74
75
104
vlc_module_begin ()
76
52
    set_shortname( "AVI" )
77
52
    set_description( N_("AVI demuxer") )
78
52
    set_capability( "demux", 212 )
79
52
    set_subcategory( SUBCAT_INPUT_DEMUX )
80
52
    add_file_extension("avi")
81
82
52
    add_bool( "avi-interleaved", false,
83
52
              INTERLEAVE_TEXT, NULL )
84
52
    add_integer( "avi-index", 0,
85
52
              INDEX_TEXT, INDEX_LONGTEXT )
86
52
        change_integer_list( pi_index, ppsz_indexes )
87
88
52
    set_callbacks( Open, Close )
89
52
vlc_module_end ()
90
91
/*****************************************************************************
92
 * Local prototypes
93
 *****************************************************************************/
94
static int Control         ( demux_t *, int, va_list );
95
static int Seek            ( demux_t *, vlc_tick_t, double, bool );
96
static int Demux_Seekable  ( demux_t * );
97
static int Demux_UnSeekable( demux_t * );
98
99
static char *FromACP( const char *str )
100
1.06k
{
101
1.06k
    return FromCharset(vlc_pgettext("GetACP", "CP1252"), str, strlen(str));
102
1.06k
}
103
104
31
#define IGNORE_ES DATA_ES
105
11.5k
#define READ_LENGTH                VLC_TICK_FROM_MS(25)
106
0
#define READ_LENGTH_NONINTERLEAVED VLC_TICK_FROM_MS(1500)
107
108
//#define AVI_DEBUG
109
110
typedef struct
111
{
112
    vlc_fourcc_t i_fourcc;
113
    uint64_t     i_pos;
114
    uint32_t     i_size;
115
    vlc_fourcc_t i_type;     /* only for AVIFOURCC_LIST */
116
117
    uint8_t      i_peek[8];  /* first 8 bytes */
118
119
    unsigned int i_stream;
120
    enum es_format_category_e i_cat;
121
} avi_packet_t;
122
123
124
typedef struct
125
{
126
    uint64_t     i_pos;
127
    uint32_t     i_flags;
128
    uint32_t     i_length;
129
    uint64_t     i_lengthtotal;
130
131
} avi_entry_t;
132
133
typedef struct
134
{
135
    uint32_t        i_size;
136
    uint32_t        i_max;
137
    avi_entry_t     *p_entry;
138
139
} avi_index_t;
140
static void avi_index_Init( avi_index_t * );
141
static void avi_index_Clean( avi_index_t * );
142
static int64_t avi_index_Append( avi_index_t *, uint64_t *, avi_entry_t * );
143
144
typedef struct
145
{
146
    bool            b_activated;
147
    bool            b_eof;
148
149
    unsigned int    i_rate; /* for audio & video */
150
    unsigned int    i_scale;/* for audio & video */
151
    unsigned int    i_samplesize;
152
153
    struct bitmapinfoheader_properties bihprops;
154
    bool            is_qnap;
155
156
    es_format_t     fmt;
157
    es_out_id_t     *p_es;
158
    int             i_next_block_flags;
159
160
    int             i_dv_audio_rate;
161
    es_out_id_t     *p_es_dv_audio;
162
    /* SPU specific */
163
    vlc_tick_t      i_last_embedded_endtime;
164
    vlc_tick_t      i_next_embedded_time;
165
166
    /* Avi Index */
167
    avi_index_t     idx;
168
169
    unsigned int    i_idxposc;  /* numero of chunk */
170
    unsigned int    i_idxposb;  /* byte in the current chunk */
171
172
    /* For VBR audio only */
173
    unsigned int    i_blockno;
174
    unsigned int    i_blocksize;
175
176
    struct
177
    {
178
        bool b_ok;
179
180
        int64_t i_toread;
181
182
        int64_t i_posf; /* where we will read :
183
                       if i_idxposb == 0 : beginning of chunk (+8 to access data)
184
                       else : point on data directly */
185
    } demuxctx;
186
187
} avi_track_t;
188
189
typedef struct
190
{
191
    vlc_tick_t i_time;
192
    vlc_tick_t i_length;
193
194
    bool  b_interleaved;
195
    bool  b_seekable;
196
    bool  b_fastseekable;
197
    bool  b_indexloaded; /* if we read indexes from end of file before starting */
198
    vlc_tick_t i_read_increment;
199
    uint32_t i_avih_flags;
200
    avi_chunk_t ck_root;
201
202
    bool  b_odml;
203
204
    uint64_t i_movi_begin;
205
    uint64_t i_movi_lastchunk_pos;   /* XXX position of last valid chunk */
206
207
    /* number of streams and information */
208
    unsigned int i_track;
209
    avi_track_t  **track;
210
211
    /* meta */
212
    vlc_meta_t  *meta;
213
    unsigned int updates;
214
215
    unsigned int       i_attachment;
216
    input_attachment_t **attachment;
217
} demux_sys_t;
218
219
17.0M
#define __EVEN(x) (((x) & 1) ? (x) + 1 : (x))
220
221
static int64_t AVI_PTSToChunk( avi_track_t *, vlc_tick_t i_pts );
222
static int64_t AVI_PTSToByte ( avi_track_t *, vlc_tick_t i_pts );
223
static vlc_tick_t AVI_GetDPTS   ( avi_track_t *, int64_t i_count );
224
static vlc_tick_t AVI_GetPTS    ( avi_track_t * );
225
226
227
static int AVI_StreamChunkFind( demux_t *, avi_track_t * );
228
static int AVI_StreamChunkSet ( demux_t *, avi_track_t *, unsigned int i_ck );
229
static int AVI_StreamBytesSet ( demux_t *, avi_track_t *, uint64_t i_byte );
230
231
vlc_fourcc_t AVI_FourccGetCodec( unsigned int i_cat, vlc_fourcc_t );
232
static int   AVI_GetKeyFlag    ( const avi_track_t *, const uint8_t * );
233
234
static int AVI_PacketGetHeader( demux_t *, avi_packet_t *p_pk );
235
static int AVI_PacketNext     ( demux_t * );
236
static int AVI_PacketSearch   ( demux_t * );
237
238
static void AVI_IndexLoad    ( demux_t * );
239
static void AVI_IndexCreate  ( demux_t * );
240
241
static void AVI_ExtractSubtitle( demux_t *, unsigned int i_stream, avi_chunk_list_t *, avi_chunk_STRING_t * );
242
static avi_track_t * AVI_GetVideoTrackForXsub( demux_sys_t * );
243
static int AVI_SeekSubtitleTrack( demux_sys_t *, avi_track_t * );
244
245
static void AVI_DvHandleAudio( demux_t *, avi_track_t *, block_t * );
246
247
static vlc_tick_t  AVI_MovieGetLength( demux_t * );
248
249
static void AVI_MetaLoad( demux_t *, avi_chunk_list_t *p_riff, avi_chunk_avih_t *p_avih );
250
251
/*****************************************************************************
252
 * Stream management
253
 *****************************************************************************/
254
static int        AVI_TrackSeek  ( demux_t *, int, vlc_tick_t );
255
static int        AVI_TrackStopFinishedStreams( demux_t *);
256
257
/* Remarks:
258
 - For VBR mp3 stream:
259
    count blocks by rounded-up chunksizes instead of chunks
260
    we need full emulation of dshow avi demuxer bugs :(
261
    fixes silly nandub-style a-v delaying in avi with vbr mp3...
262
    (from mplayer 2002/08/02)
263
 - to complete....
264
 */
265
266
995
#define QNAP_VIDEO_HEADER_SIZE 56
267
/* https://github.com/qnap-dev/qnap-qiot-sdks/blob/master/doc/QVRPro/live_stream_parser.cpp#L90 */
268
static bool IsQNAPCodec(uint32_t biCompression)
269
8.18k
{
270
8.18k
    switch (biCompression)
271
8.18k
    {
272
1
        case QNAP_FCC_w264:
273
64
        case QNAP_FCC_q264:
274
138
        case QNAP_FCC_Q264:
275
139
        case QNAP_FCC_wMP4:
276
163
        case QNAP_FCC_qMP4:
277
164
        case QNAP_FCC_QMP4:
278
166
        case QNAP_FCC_wIVG:
279
167
        case QNAP_FCC_qIVG:
280
168
        case QNAP_FCC_QIVG:
281
168
            return true;
282
8.01k
        default:
283
8.01k
            return false;
284
8.18k
    }
285
8.18k
}
286
287
20.6k
#define XSUB_HEADER_SIZE 0x1B
288
static int ExtractXsubSampleInfo( const uint8_t *p_buf,
289
                                  vlc_tick_t *pi_start, vlc_tick_t *pi_end )
290
5.84k
{
291
5.84k
    unsigned t[8];
292
5.84k
    char buffer[XSUB_HEADER_SIZE + 1];
293
5.84k
    memcpy( buffer, p_buf, XSUB_HEADER_SIZE );
294
5.84k
    buffer[XSUB_HEADER_SIZE] = '\0';
295
5.84k
    if( sscanf( buffer, "[%u:%2u:%2u.%3u-%u:%2u:%2u.%3u]",
296
5.84k
                &t[0], &t[1], &t[2], &t[3], &t[4], &t[5], &t[6], &t[7] ) != 8 )
297
5.84k
        return VLC_EGENERIC;
298
0
    *pi_start = vlc_tick_from_sec( t[0] * 3600 + t[1] * 60 + t[2] ) +
299
0
                                   VLC_TICK_FROM_MS(t[3]);
300
0
    *pi_end = vlc_tick_from_sec( t[4] * 3600 + t[5] * 60 + t[6] ) +
301
0
                                 VLC_TICK_FROM_MS(t[7]);
302
0
    return VLC_SUCCESS;
303
5.84k
}
304
305
static int AVI_PeekSample( stream_t *s, size_t i_skip,
306
                           const uint8_t **pp_peek, size_t i_peek )
307
8.65k
{
308
8.65k
    ssize_t i_ret = vlc_stream_Peek( s, pp_peek, i_skip + i_peek );
309
8.65k
    *pp_peek += i_skip;
310
8.65k
    if ( i_ret < 0 || (size_t) i_ret != i_skip + i_peek )
311
2.93k
        return VLC_EGENERIC;
312
5.72k
    return VLC_SUCCESS;
313
8.65k
}
314
315
static vlc_tick_t AVI_GetXsubSampleTimeAt( stream_t *s, uint64_t pos )
316
8.65k
{
317
8.65k
    const uint8_t *p_peek;
318
8.65k
    vlc_tick_t i_nzstart, i_nzend;
319
8.65k
    if( vlc_stream_Seek( s, pos ) != VLC_SUCCESS ||
320
8.65k
        AVI_PeekSample( s, 8, &p_peek, XSUB_HEADER_SIZE ) ||
321
8.65k
        ExtractXsubSampleInfo( p_peek, &i_nzstart, &i_nzend ) )
322
8.65k
        return VLC_TICK_INVALID;
323
0
    return VLC_TICK_0 + i_nzstart;
324
8.65k
}
325
326
/*****************************************************************************
327
 * Close: frees unused data
328
 *****************************************************************************/
329
static void Close ( vlc_object_t * p_this )
330
13.6k
{
331
13.6k
    demux_t *    p_demux = (demux_t *)p_this;
332
13.6k
    demux_sys_t *p_sys = p_demux->p_sys  ;
333
334
30.9k
    for( unsigned int i = 0; i < p_sys->i_track; i++ )
335
17.2k
    {
336
17.2k
        if( p_sys->track[i] )
337
17.2k
        {
338
17.2k
            es_format_Clean( &p_sys->track[i]->fmt );
339
17.2k
            avi_index_Clean( &p_sys->track[i]->idx );
340
17.2k
            free( p_sys->track[i] );
341
17.2k
        }
342
17.2k
    }
343
13.6k
    free( p_sys->track );
344
345
13.6k
    AVI_ChunkFreeRoot( p_demux->s, &p_sys->ck_root );
346
13.6k
    if( p_sys->meta )
347
11.5k
        vlc_meta_Delete( p_sys->meta );
348
349
13.6k
    for( unsigned i = 0; i < p_sys->i_attachment; i++)
350
0
        vlc_input_attachment_Release(p_sys->attachment[i]);
351
13.6k
    free(p_sys->attachment);
352
353
13.6k
    free( p_sys );
354
13.6k
}
355
356
/*****************************************************************************
357
 * Open: check file and initializes AVI structures
358
 *****************************************************************************/
359
static int Open( vlc_object_t * p_this )
360
13.6k
{
361
13.6k
    demux_t  *p_demux = (demux_t *)p_this;
362
13.6k
    demux_sys_t     *p_sys;
363
364
13.6k
    bool       b_index = false, b_aborted = false;
365
13.6k
    int              i_do_index;
366
367
13.6k
    avi_chunk_list_t    *p_riff;
368
13.6k
    avi_chunk_list_t    *p_hdrl, *p_movi;
369
13.6k
    avi_chunk_avih_t    *p_avih;
370
371
13.6k
    unsigned int i_track;
372
13.6k
    unsigned int i_peeker;
373
374
13.6k
    const uint8_t *p_peek;
375
376
    /* Is it an avi file ? */
377
13.6k
    if( vlc_stream_Peek( p_demux->s, &p_peek, 200 ) < 200 )
378
22
        return VLC_EGENERIC;
379
380
174k
    for( i_peeker = 0; i_peeker < 188; i_peeker++ )
381
174k
    {
382
174k
        if( !strncmp( (char *)&p_peek[0], "RIFF", 4 ) && !strncmp( (char *)&p_peek[8], "AVI ", 4 ) )
383
13.5k
            break;
384
160k
        if( !strncmp( (char *)&p_peek[0], "ON2 ", 4 ) && !strncmp( (char *)&p_peek[8], "ON2f", 4 ) )
385
66
            break;
386
160k
        p_peek++;
387
160k
    }
388
13.6k
    if( i_peeker == 188 )
389
30
    {
390
30
        return VLC_EGENERIC;
391
30
    }
392
393
13.6k
    if( i_peeker > 0 && vlc_stream_Read( p_demux->s, NULL, i_peeker ) != i_peeker )
394
0
        return VLC_EGENERIC;
395
396
    /* Initialize input structures. */
397
13.6k
    p_sys = p_demux->p_sys = calloc( 1, sizeof(demux_sys_t) );
398
13.6k
    if( unlikely(!p_sys) )
399
0
        return VLC_EGENERIC;
400
13.6k
    p_sys->b_odml   = false;
401
13.6k
    p_sys->meta     = NULL;
402
13.6k
    TAB_INIT(p_sys->i_track, p_sys->track);
403
13.6k
    TAB_INIT(p_sys->i_attachment, p_sys->attachment);
404
405
13.6k
    vlc_stream_Control( p_demux->s, STREAM_CAN_FASTSEEK,
406
13.6k
                        &p_sys->b_fastseekable );
407
13.6k
    vlc_stream_Control( p_demux->s, STREAM_CAN_SEEK, &p_sys->b_seekable );
408
409
13.6k
    p_sys->b_interleaved = var_InheritBool( p_demux, "avi-interleaved" );
410
411
13.6k
    if( AVI_ChunkReadRoot( p_demux->s, &p_sys->ck_root ) )
412
0
    {
413
0
        msg_Err( p_demux, "avi module discarded (invalid file)" );
414
0
        free(p_sys);
415
0
        return VLC_EGENERIC;
416
0
    }
417
418
13.6k
    if( AVI_ChunkCount( &p_sys->ck_root, AVIFOURCC_RIFF, true ) > 1 )
419
207
    {
420
207
        unsigned int i_count =
421
207
            AVI_ChunkCount( &p_sys->ck_root, AVIFOURCC_RIFF, true );
422
423
207
        msg_Warn( p_demux, "multiple riff -> OpenDML ?" );
424
2.86k
        for( unsigned i = 1; i < i_count; i++ )
425
2.66k
        {
426
2.66k
            avi_chunk_list_t *p_sysx;
427
428
2.66k
            p_sysx = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, i, true );
429
2.66k
            if( p_sysx && p_sysx->i_type == AVIFOURCC_AVIX )
430
6
            {
431
6
                msg_Warn( p_demux, "detected OpenDML file" );
432
6
                p_sys->b_odml = true;
433
6
                break;
434
6
            }
435
2.66k
        }
436
207
    }
437
438
13.6k
    p_riff  = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0, true );
439
13.6k
    p_hdrl  = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0, true );
440
13.6k
    p_movi  = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0, true );
441
13.6k
    if( !p_movi )
442
2.23k
        p_movi  = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_movi, 0, true );
443
444
13.6k
    if( !p_hdrl || !p_movi )
445
1.96k
    {
446
1.96k
        msg_Err( p_demux, "invalid file: cannot find hdrl or movi chunks" );
447
1.96k
        goto error;
448
1.96k
    }
449
450
11.6k
    if( !( p_avih = AVI_ChunkFind( p_hdrl, AVIFOURCC_avih, 0, false ) ) )
451
8
    {
452
8
        msg_Err( p_demux, "invalid file: cannot find avih chunk" );
453
8
        goto error;
454
8
    }
455
11.6k
    i_track = AVI_ChunkCount( p_hdrl, AVIFOURCC_strl, true );
456
11.6k
    if( p_avih->i_streams != i_track )
457
10.0k
    {
458
10.0k
        msg_Warn( p_demux,
459
10.0k
                  "found %d stream but %d are declared",
460
10.0k
                  i_track, p_avih->i_streams );
461
10.0k
    }
462
11.6k
    if( i_track == 0 )
463
73
    {
464
73
        msg_Err( p_demux, "no stream defined!" );
465
73
        goto error;
466
73
    }
467
468
    /* print information on streams */
469
11.5k
    msg_Dbg( p_demux, "AVIH: %d stream, flags %s%s%s%s ",
470
11.5k
             i_track,
471
11.5k
             p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
472
11.5k
             p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
473
11.5k
             p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
474
11.5k
             p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
475
476
11.5k
    p_sys->b_interleaved |= (p_avih->i_flags & AVIF_ISINTERLEAVED);
477
478
    /* Set callbacks */
479
11.5k
    p_demux->pf_control = Control;
480
481
11.5k
    if( p_sys->b_fastseekable )
482
11.5k
    {
483
11.5k
        p_demux->pf_demux = Demux_Seekable;
484
11.5k
        p_sys->i_read_increment = READ_LENGTH;
485
11.5k
    }
486
0
    else if( p_sys->b_seekable )
487
0
    {
488
0
        p_demux->pf_demux = Demux_Seekable;
489
0
        p_sys->i_read_increment = READ_LENGTH_NONINTERLEAVED;
490
0
        if( !p_sys->b_interleaved )
491
0
            msg_Warn( p_demux, "Non interleaved content over slow seekable, "
492
0
                               "expect bad performance" );
493
0
    }
494
0
    else
495
0
    {
496
0
        msg_Warn( p_demux, "Non seekable content " );
497
498
0
        p_demux->pf_demux = Demux_UnSeekable;
499
0
        p_sys->i_read_increment = READ_LENGTH_NONINTERLEAVED;
500
         /* non seekable and non interleaved case ? well... */
501
0
        if( !p_sys->b_interleaved )
502
0
        {
503
0
            msg_Warn( p_demux, "Non seekable non interleaved content, "
504
0
                               "disabling other tracks" );
505
0
            i_track = __MIN(i_track, 1);
506
0
        }
507
0
    }
508
509
11.5k
    AVI_MetaLoad( p_demux, p_riff, p_avih );
510
11.5k
    p_sys->i_avih_flags = p_avih->i_flags;
511
512
    /* now read info on each stream and create ES */
513
31.8k
    for( unsigned i = 0 ; i < i_track; i++ )
514
20.3k
    {
515
20.3k
        avi_track_t           *tk     = calloc( 1, sizeof( avi_track_t ) );
516
20.3k
        if( unlikely( !tk ) )
517
0
            goto error;
518
519
20.3k
        avi_chunk_list_t      *p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i, true );
520
20.3k
        avi_chunk_strh_t      *p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0, false );
521
20.3k
        avi_chunk_STRING_t    *p_strn = AVI_ChunkFind( p_strl, AVIFOURCC_strn, 0, false );
522
20.3k
        avi_chunk_strf_auds_t *p_auds = NULL;
523
20.3k
        avi_chunk_strf_vids_t *p_vids = NULL;
524
525
20.3k
        tk->b_eof = false;
526
20.3k
        tk->b_activated = true;
527
528
20.3k
        p_vids = (avi_chunk_strf_vids_t*)AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0, false );
529
20.3k
        p_auds = (avi_chunk_strf_auds_t*)p_vids;
530
531
20.3k
        if( p_strl == NULL || p_strh == NULL || p_vids == NULL )
532
2.15k
        {
533
2.15k
            msg_Warn( p_demux, "stream[%d] incomplete", i );
534
2.15k
            free( tk );
535
2.15k
            continue;
536
2.15k
        }
537
538
18.1k
        tk->i_rate  = p_strh->i_rate;
539
18.1k
        tk->i_scale = p_strh->i_scale;
540
18.1k
        tk->i_samplesize = p_strh->i_samplesize;
541
18.1k
        msg_Dbg( p_demux, "stream[%u] rate:%u scale:%u samplesize:%u",
542
18.1k
                i, tk->i_rate, tk->i_scale, tk->i_samplesize );
543
544
18.1k
        switch( p_strh->i_type )
545
18.1k
        {
546
8.54k
            case( AVIFOURCC_auds ):
547
8.54k
            {
548
8.54k
                es_format_Init( &tk->fmt, AUDIO_ES, 0 );
549
550
8.54k
                if( p_auds->p_wf->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
551
8.54k
                    p_auds->p_wf->cbSize >= sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) )
552
18
                {
553
18
                    WAVEFORMATEXTENSIBLE *p_wfe = container_of(p_auds->p_wf, WAVEFORMATEXTENSIBLE, Format);
554
18
                    tk->fmt.i_codec = AVI_FourccGetCodec( AUDIO_ES, p_wfe->SubFormat.Data1 );
555
18
                }
556
8.52k
                else
557
8.52k
                    tk->fmt.i_codec = AVI_FourccGetCodec( AUDIO_ES, p_auds->p_wf->wFormatTag );
558
559
8.54k
                tk->i_blocksize = p_auds->p_wf->nBlockAlign;
560
561
                /* Fix blocksize == 0 and force interleaving PCM chunks samplesize == 0 */
562
8.54k
                if( tk->i_samplesize == 0 || tk->i_blocksize == 0 )
563
4.15k
                {
564
4.15k
                    vlc_fourcc_t i_codec = vlc_fourcc_GetCodecAudio( tk->fmt.i_codec,
565
4.15k
                                                                     p_auds->p_wf->wBitsPerSample );
566
4.15k
                    unsigned bps = aout_BitsPerSample( i_codec );
567
4.15k
                    if( bps > 0 ) /* PCM audio */
568
770
                    {
569
770
                        if( tk->i_blocksize == 0 )
570
600
                            tk->i_blocksize = bps * p_auds->p_wf->nChannels / 8;
571
770
                        if( tk->i_samplesize == 0 )
572
198
                            tk->i_samplesize = tk->i_blocksize;
573
770
                        tk->fmt.b_packetized = true;
574
770
                    }
575
3.38k
                    else if( tk->i_blocksize == 0 )
576
2.01k
                    {
577
2.01k
                        tk->i_blocksize = 1;
578
2.01k
                    }
579
4.15k
                }
580
4.38k
                else if( tk->i_samplesize != tk->i_blocksize )
581
4.12k
                {
582
4.12k
                    msg_Warn( p_demux, "track[%u] samplesize=%u and blocksize=%u are not equal."
583
4.12k
                                       "Using blocksize as a workaround.",
584
4.12k
                                       i, tk->i_samplesize, tk->i_blocksize );
585
4.12k
                    tk->i_samplesize = tk->i_blocksize;
586
4.12k
                }
587
588
                /* fix VBR decoding */
589
8.54k
                if( tk->fmt.i_codec == VLC_CODEC_VORBIS ||
590
8.54k
                    tk->fmt.i_codec == VLC_CODEC_FLAC )
591
1
                {
592
1
                    tk->i_blocksize = 0;
593
1
                }
594
595
8.54k
                if ( tk->fmt.i_codec == VLC_CODEC_MP4A )
596
348
                {
597
348
                    tk->i_samplesize = 0; /* ADTS/AAC VBR */
598
348
                }
599
600
                /* Fix broken scale/rate */
601
8.54k
                if ( tk->fmt.i_codec == VLC_CODEC_ADPCM_IMA_WAV &&
602
8.54k
                     tk->i_samplesize && tk->i_samplesize > tk->i_rate )
603
417
                {
604
417
                    tk->i_scale = 1017;
605
417
                    tk->i_rate = p_auds->p_wf->nSamplesPerSec;
606
417
                }
607
608
                /* From libavformat */
609
                /* Fix broken sample size (which is mp2 num samples / frame) #12722 */
610
8.54k
                if( tk->fmt.i_codec == VLC_CODEC_MPGA &&
611
8.54k
                    tk->i_samplesize == 1152 && p_auds->p_wf->nBlockAlign == 1152 )
612
1
                {
613
1
                    p_auds->p_wf->nBlockAlign = tk->i_samplesize = 0;
614
1
                }
615
616
8.54k
                tk->fmt.audio.i_channels        = p_auds->p_wf->nChannels;
617
8.54k
                tk->fmt.audio.i_rate            = p_auds->p_wf->nSamplesPerSec;
618
8.54k
                tk->fmt.i_bitrate               = p_auds->p_wf->nAvgBytesPerSec*8;
619
8.54k
                tk->fmt.audio.i_blockalign      = p_auds->p_wf->nBlockAlign;
620
8.54k
                tk->fmt.audio.i_bitspersample   = p_auds->p_wf->wBitsPerSample;
621
8.54k
                tk->fmt.b_packetized            = !tk->i_blocksize;
622
623
8.54k
                avi_chunk_list_t *p_info = AVI_ChunkFind( p_riff, AVIFOURCC_INFO, 0, true );
624
8.54k
                if( p_info )
625
3.56k
                {
626
3.56k
                    int i_chunk = AVIFOURCC_IAS1 + ((i - 1) << 24);
627
3.56k
                    avi_chunk_STRING_t *p_lang = AVI_ChunkFind( p_info, i_chunk, 0, false );
628
3.56k
                    if( p_lang != NULL && p_lang->p_str != NULL )
629
0
                        tk->fmt.psz_language = FromACP( p_lang->p_str );
630
3.56k
                }
631
632
8.54k
                msg_Dbg( p_demux,
633
8.54k
                    "stream[%u] audio(0x%x - %s) %d channels %dHz %dbits",
634
8.54k
                    i, p_auds->p_wf->wFormatTag,
635
8.54k
                    vlc_fourcc_GetDescription(AUDIO_ES, tk->fmt.i_codec),
636
8.54k
                    p_auds->p_wf->nChannels,
637
8.54k
                    p_auds->p_wf->nSamplesPerSec,
638
8.54k
                    p_auds->p_wf->wBitsPerSample );
639
640
8.54k
                const size_t i_cboff = sizeof(WAVEFORMATEX);
641
8.54k
                const size_t i_incboff = ( p_auds->p_wf->wFormatTag == WAVE_FORMAT_EXTENSIBLE ) ?
642
8.50k
                                          sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX): 0;
643
8.54k
                if( p_auds->i_chunk_size >= i_cboff + p_auds->p_wf->cbSize &&
644
8.54k
                    p_auds->p_wf->cbSize > i_incboff )
645
296
                {
646
296
                    int i_extra = p_auds->p_wf->cbSize - i_incboff;
647
296
                    tk->fmt.p_extra = malloc( i_extra );
648
296
                    if( unlikely(tk->fmt.p_extra == NULL) )
649
0
                    {
650
0
                        es_format_Clean( &tk->fmt );
651
0
                        free( tk );
652
0
                        goto error;
653
0
                    }
654
296
                    tk->fmt.i_extra = i_extra;
655
296
                    memcpy( tk->fmt.p_extra, ((uint8_t *)(&p_auds->p_wf[1])) + i_incboff, i_extra );
656
296
                }
657
8.54k
                break;
658
8.54k
            }
659
660
8.54k
            case( AVIFOURCC_vids ):
661
7.40k
            {
662
7.40k
                if( p_vids->p_bih->biCompression == FOURCC_DXSB )
663
50
                {
664
50
                   msg_Dbg( p_demux, "stream[%u] subtitles", i );
665
50
                   es_format_Init( &tk->fmt, SPU_ES, p_vids->p_bih->biCompression );
666
50
                   tk->fmt.subs.spu.i_original_frame_width = p_vids->p_bih->biWidth;
667
50
                   tk->fmt.subs.spu.i_original_frame_height = p_vids->p_bih->biHeight;
668
50
                   break;
669
50
                }
670
671
7.35k
                es_format_Init( &tk->fmt, VIDEO_ES, 0 );
672
673
7.35k
                if( ParseBitmapInfoHeader( p_vids->p_bih, p_vids->i_chunk_size, &tk->fmt,
674
7.35k
                                           &tk->bihprops ) != VLC_SUCCESS )
675
35
                {
676
35
                    es_format_Clean( &tk->fmt );
677
35
                    free( tk );
678
35
                    goto error;
679
35
                }
680
681
7.31k
                if( tk->fmt.i_codec == VLC_CODEC_MP4V &&
682
7.31k
                    !strncasecmp( (char*)&p_strh->i_handler, "XVID", 4 ) )
683
1
                {
684
1
                    tk->fmt.i_codec           =
685
1
                    tk->fmt.i_original_fourcc = FOURCC_XVID;
686
1
                    tk->fmt.b_packetized = false;
687
1
                }
688
689
7.31k
                if( IsQNAPCodec( p_vids->p_bih->biCompression ) )
690
161
                {
691
161
                    tk->is_qnap = true;
692
161
                    tk->fmt.b_packetized = false;
693
161
                }
694
695
7.31k
                tk->i_samplesize = 0;
696
7.31k
                tk->fmt.video.i_frame_rate = tk->i_rate;
697
7.31k
                tk->fmt.video.i_frame_rate_base = tk->i_scale;
698
699
7.31k
                avi_chunk_vprp_t *p_vprp = AVI_ChunkFind( p_strl, AVIFOURCC_vprp, 0, false );
700
7.31k
                if( p_vprp )
701
21
                {
702
21
                    uint32_t i_frame_aspect_ratio = p_vprp->i_frame_aspect_ratio;
703
21
                    if( p_vprp->i_video_format_token >= 1 &&
704
21
                        p_vprp->i_video_format_token <= 4 )
705
3
                        i_frame_aspect_ratio = 0x00040003;
706
21
                    tk->fmt.video.i_sar_num = ((i_frame_aspect_ratio >> 16) & 0xffff) *
707
21
                                              tk->fmt.video.i_height;
708
21
                    tk->fmt.video.i_sar_den = ((i_frame_aspect_ratio >>  0) & 0xffff) *
709
21
                                              tk->fmt.video.i_width;
710
21
                }
711
712
7.31k
                msg_Dbg( p_demux, "stream[%u] video(%4.4s) %"PRIu32"x%"PRIu32" %dbpp %ffps",
713
7.31k
                         i, (char*)&p_vids->p_bih->biCompression,
714
7.31k
                         p_vids->p_bih->biWidth,
715
7.31k
                         (p_vids->p_bih->biHeight <= INT_MAX) ? p_vids->p_bih->biHeight
716
7.31k
                                                              : -1 * p_vids->p_bih->biHeight,
717
7.31k
                         p_vids->p_bih->biBitCount,
718
7.31k
                         (float)tk->i_rate/(float)tk->i_scale );
719
7.31k
                break;
720
7.35k
            }
721
722
198
            case( AVIFOURCC_txts):
723
198
                msg_Dbg( p_demux, "stream[%u] subtitle attachment", i );
724
198
                AVI_ExtractSubtitle( p_demux, i, p_strl, p_strn );
725
198
                free( tk );
726
198
                continue;
727
728
195
            case( AVIFOURCC_iavs):
729
1.53k
            case( AVIFOURCC_ivas):
730
1.53k
                msg_Dbg( p_demux, "stream[%u] iavs with handler %4.4s", i, (char *)&p_strh->i_handler );
731
1.53k
                es_format_Init( &tk->fmt, VIDEO_ES, AVI_FourccGetCodec( VIDEO_ES, p_strh->i_handler ) );
732
1.53k
                tk->i_samplesize = 0;
733
1.53k
                tk->i_dv_audio_rate = tk->fmt.i_codec == VLC_CODEC_DV ? -1 : 0;
734
735
1.53k
                tk->fmt.video.i_visible_width =
736
1.53k
                tk->fmt.video.i_width  = p_avih->i_width;
737
1.53k
                tk->fmt.video.i_visible_height =
738
1.53k
                tk->fmt.video.i_height = p_avih->i_height;
739
1.53k
                break;
740
741
3
            case( AVIFOURCC_mids):
742
3
                msg_Dbg( p_demux, "stream[%u] midi is UNSUPPORTED", i );
743
                /* fall through */
744
745
480
            default:
746
480
                msg_Warn( p_demux, "stream[%u] unknown type %4.4s", i, (char *)&p_strh->i_type );
747
480
                free( tk );
748
480
                continue;
749
18.1k
        }
750
751
17.4k
        if( tk->fmt.i_cat != SPU_ES &&
752
17.4k
           (!tk->i_scale || !tk->i_rate || !(tk->i_rate * CLOCK_FREQ / tk->i_scale)) )
753
159
        {
754
159
            msg_Warn( p_demux, "stream[%u] has invalid timescale", i );
755
159
            es_format_Clean(&tk->fmt);
756
159
            free( tk );
757
159
            continue;
758
159
        }
759
760
17.2k
        tk->fmt.i_id = i;
761
17.2k
        if( p_strn && p_strn->p_str )
762
13
            tk->fmt.psz_description = FromACP( p_strn->p_str );
763
17.2k
        tk->p_es = es_out_Add( p_demux->out, &tk->fmt );
764
17.2k
        TAB_APPEND( p_sys->i_track, p_sys->track, tk );
765
17.2k
    }
766
767
11.5k
    if( p_sys->i_track <= 0 )
768
284
    {
769
284
        msg_Err( p_demux, "no valid track" );
770
284
        goto error;
771
284
    }
772
773
11.2k
    i_do_index = var_InheritInteger( p_demux, "avi-index" );
774
11.2k
    if( i_do_index == 1 ) /* Always fix */
775
0
    {
776
0
aviindex:
777
0
        if( p_sys->b_fastseekable )
778
0
        {
779
0
            AVI_IndexCreate( p_demux );
780
0
        }
781
0
        else if( p_sys->b_seekable )
782
0
        {
783
0
            AVI_IndexLoad( p_demux );
784
0
        }
785
0
        else
786
0
        {
787
0
            msg_Warn( p_demux, "cannot create index (unseekable stream)" );
788
0
        }
789
0
    }
790
11.2k
    else if( p_sys->b_seekable )
791
11.2k
    {
792
11.2k
        AVI_IndexLoad( p_demux );
793
11.2k
    }
794
795
    /* *** movie length in vlc_tick_t *** */
796
11.2k
    p_sys->i_length = AVI_MovieGetLength( p_demux );
797
798
    /* Check the index completeness */
799
11.2k
    unsigned int i_idx_totalframes = 0;
800
28.5k
    for( unsigned int i = 0; i < p_sys->i_track; i++ )
801
17.2k
    {
802
17.2k
        const avi_track_t *tk = p_sys->track[i];
803
17.2k
        if( tk->fmt.i_cat == VIDEO_ES && tk->idx.p_entry )
804
207
            i_idx_totalframes = __MAX(i_idx_totalframes, tk->idx.i_size);
805
17.2k
    }
806
11.2k
    if( i_idx_totalframes != p_avih->i_totalframes &&
807
11.2k
        p_sys->i_length < VLC_TICK_FROM_US( p_avih->i_totalframes *
808
11.2k
                                            p_avih->i_microsecperframe ) )
809
8.28k
    {
810
8.28k
        msg_Warn( p_demux, "broken or missing index, 'seek' will be "
811
8.28k
                           "approximative or will exhibit strange behavior" );
812
8.28k
        if( (i_do_index == 0 || i_do_index == 3) && !b_index )
813
8.28k
        {
814
8.28k
            if( !p_sys->b_fastseekable ) {
815
0
                b_index = true;
816
0
                goto aviindex;
817
0
            }
818
8.28k
            if( i_do_index == 0 )
819
8.28k
            {
820
8.28k
                const char *psz_msg = _(
821
8.28k
                    "Because this file index is broken or missing, "
822
8.28k
                    "seeking will not work correctly.\n"
823
8.28k
                    "VLC won't repair your file but can temporary fix this "
824
8.28k
                    "problem by building an index in memory.\n"
825
8.28k
                    "This step might take a long time on a large file.\n"
826
8.28k
                    "What do you want to do?");
827
8.28k
                switch( vlc_dialog_wait_question( p_demux,
828
8.28k
                                                  VLC_DIALOG_QUESTION_NORMAL,
829
8.28k
                                                  _("Do not play"),
830
8.28k
                                                  _("Build index then play"),
831
8.28k
                                                  _("Play as is"),
832
8.28k
                                                  _("Broken or missing Index"),
833
8.28k
                                                  "%s", psz_msg ) )
834
8.28k
                {
835
0
                    case 0:
836
0
                        b_aborted = true;
837
0
                        goto error;
838
0
                    case 1:
839
0
                        b_index = true;
840
0
                        msg_Dbg( p_demux, "Fixing AVI index" );
841
0
                        goto aviindex;
842
8.28k
                }
843
8.28k
            }
844
0
            else
845
0
            {
846
0
                b_index = true;
847
0
                msg_Dbg( p_demux, "Fixing AVI index" );
848
0
                goto aviindex;
849
0
            }
850
8.28k
        }
851
8.28k
    }
852
853
    /* fix some BeOS MediaKit generated file */
854
28.5k
    for( unsigned i = 0 ; i < p_sys->i_track; i++ )
855
17.2k
    {
856
17.2k
        avi_track_t         *tk = p_sys->track[i];
857
17.2k
        avi_chunk_list_t    *p_strl;
858
17.2k
        avi_chunk_strf_auds_t    *p_auds;
859
860
17.2k
        if( tk->fmt.i_cat != AUDIO_ES )
861
8.87k
        {
862
8.87k
            continue;
863
8.87k
        }
864
8.40k
        if( tk->idx.i_size < 1 ||
865
8.40k
            tk->i_scale != 1 ||
866
8.40k
            tk->i_samplesize != 0 )
867
8.39k
        {
868
8.39k
            continue;
869
8.39k
        }
870
3
        p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, tk->fmt.i_id, true );
871
3
        p_auds = AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0, false );
872
873
3
        if( p_auds &&
874
3
            p_auds->p_wf->wFormatTag != WAVE_FORMAT_PCM &&
875
3
            tk->i_rate == p_auds->p_wf->nSamplesPerSec )
876
0
        {
877
0
            int64_t i_track_length =
878
0
                tk->idx.p_entry[tk->idx.i_size-1].i_length +
879
0
                tk->idx.p_entry[tk->idx.i_size-1].i_lengthtotal;
880
0
            vlc_tick_t i_length = VLC_TICK_FROM_US( p_avih->i_totalframes *
881
0
                                                    p_avih->i_microsecperframe );
882
883
0
            if( i_length == 0 )
884
0
            {
885
0
                msg_Warn( p_demux, "track[%u] cannot be fixed (BeOS MediaKit generated)", i );
886
0
                continue;
887
0
            }
888
0
            tk->i_samplesize = 1;
889
0
            tk->i_rate       = i_track_length  * CLOCK_FREQ / i_length;
890
0
            msg_Warn( p_demux, "track[%u] fixed with rate=%u scale=%u (BeOS MediaKit generated)", i, tk->i_rate, tk->i_scale );
891
0
        }
892
3
    }
893
894
11.2k
    if( p_sys->b_seekable )
895
11.2k
    {
896
        /* we have read all chunk so go back to movi */
897
11.2k
        if( vlc_stream_Seek( p_demux->s, p_movi->i_chunk_pos ) )
898
0
            goto error;
899
11.2k
    }
900
    /* Skip movi header */
901
11.2k
    if( vlc_stream_Read( p_demux->s, NULL, 12 ) != 12 )
902
0
        goto error;
903
904
11.2k
    p_sys->i_movi_begin = p_movi->i_chunk_pos;
905
11.2k
    return VLC_SUCCESS;
906
907
2.36k
error:
908
2.36k
    Close( p_this );
909
2.36k
    return b_aborted ? VLC_ETIMEOUT : VLC_EGENERIC;
910
11.2k
}
911
912
/*****************************************************************************
913
 * ReadFrame: Reads frame, using stride if necessary
914
 *****************************************************************************/
915
916
static block_t * ReadFrame( demux_t *p_demux, const avi_track_t *tk,
917
                            uint32_t i_header, uint32_t i_osize )
918
16.8M
{
919
    /* skip header */
920
16.8M
    if( i_header )
921
10.1M
    {
922
10.1M
        assert(i_header % 8 == 0);
923
10.1M
        ssize_t i_skip = vlc_stream_Read( p_demux->s, NULL, i_header );
924
10.1M
        if( i_skip < 0 || (size_t) i_skip < i_header )
925
914k
            return NULL;
926
10.1M
    }
927
928
    /* read size padded on word boundary */
929
15.9M
    uint32_t i_size = __EVEN(i_osize);
930
931
15.9M
    if( i_size == 0 )
932
529
        return block_Alloc(0); /* vlc_stream_Block can't read/alloc 0 sized */
933
934
15.9M
    block_t *p_frame = vlc_stream_Block( p_demux->s, i_size );
935
15.9M
    if ( !p_frame )
936
14.8M
        return p_frame;
937
938
1.07M
    if( i_osize == i_size - 1 )
939
1.04M
        p_frame->i_buffer--;
940
941
1.07M
    if( tk->fmt.i_codec == FOURCC_DXSB && p_frame->i_buffer > XSUB_HEADER_SIZE )
942
123
    {
943
123
        vlc_tick_t i_start, i_end;
944
123
        if( !ExtractXsubSampleInfo( p_frame->p_buffer, &i_start, &i_end ) )
945
0
        {
946
0
            p_frame->i_dts = p_frame->i_pts = VLC_TICK_0 + i_start;
947
0
            if( i_end > i_start )
948
0
                p_frame->i_length = i_start - i_end;
949
0
        }
950
123
    }
951
952
1.07M
    if( tk->bihprops.i_stride > INT32_MAX - 3 )
953
246
    {
954
246
        p_frame->i_buffer = 0;
955
246
        return p_frame;
956
246
    }
957
958
1.07M
    const unsigned int i_stride_bytes = (tk->bihprops.i_stride + 3) & ~3;
959
960
1.07M
    if ( !tk->bihprops.i_stride || !i_stride_bytes )
961
1.07M
        return p_frame;
962
963
649
    if( p_frame->i_buffer < i_stride_bytes )
964
202
    {
965
202
        p_frame->i_buffer = 0;
966
202
        return p_frame;
967
202
    }
968
969
447
    if( !tk->bihprops.b_flipped )
970
107
    {
971
107
        const uint8_t *p_src = p_frame->p_buffer + i_stride_bytes;
972
107
        const uint8_t *p_end = p_frame->p_buffer + p_frame->i_buffer;
973
107
        uint8_t *p_dst = p_frame->p_buffer + tk->bihprops.i_stride;
974
975
107
        p_frame->i_buffer = tk->bihprops.i_stride;
976
977
4.38k
        while ( p_src + i_stride_bytes <= p_end )
978
4.27k
        {
979
4.27k
            memmove( p_dst, p_src, tk->bihprops.i_stride );
980
4.27k
            p_src += i_stride_bytes;
981
4.27k
            p_dst += tk->bihprops.i_stride;
982
4.27k
            p_frame->i_buffer += tk->bihprops.i_stride;
983
4.27k
        }
984
107
    }
985
340
    else
986
340
    {
987
340
        block_t *p_flippedframe = block_Alloc( p_frame->i_buffer );
988
340
        if ( !p_flippedframe )
989
0
        {
990
0
            block_Release( p_frame );
991
0
            return NULL;
992
0
        }
993
994
340
        unsigned int i_lines = p_frame->i_buffer / i_stride_bytes;
995
340
        const uint8_t *p_src = p_frame->p_buffer + i_lines * i_stride_bytes;
996
340
        uint8_t *p_dst = p_flippedframe->p_buffer;
997
998
340
        p_flippedframe->i_buffer = 0;
999
1000
35.2k
        while ( i_lines-- > 0 )
1001
34.8k
        {
1002
34.8k
            p_src -= i_stride_bytes;
1003
34.8k
            memcpy( p_dst, p_src, tk->bihprops.i_stride );
1004
34.8k
            p_dst += tk->bihprops.i_stride;
1005
34.8k
            p_flippedframe->i_buffer += tk->bihprops.i_stride;
1006
34.8k
        }
1007
1008
340
        block_Release( p_frame );
1009
340
        p_frame = p_flippedframe;
1010
340
    }
1011
1012
447
    return p_frame;
1013
447
}
1014
1015
/*****************************************************************************
1016
 * SendFrame: Sends frame to ES and does payload processing
1017
 *****************************************************************************/
1018
static void AVI_SendFrame( demux_t *p_demux, avi_track_t *tk, block_t *p_frame )
1019
1.07M
{
1020
1.07M
    demux_sys_t *p_sys = p_demux->p_sys;
1021
1022
1.07M
    if( tk->fmt.i_cat != VIDEO_ES )
1023
1.07M
        p_frame->i_dts = p_frame->i_pts;
1024
7.54k
    else
1025
7.54k
    {
1026
7.54k
        p_frame->i_dts = p_frame->i_pts;
1027
7.54k
        p_frame->i_pts = VLC_TICK_INVALID;
1028
7.54k
    }
1029
1030
1.07M
    if( tk->i_dv_audio_rate )
1031
198
        AVI_DvHandleAudio( p_demux, tk, p_frame );
1032
1033
    /* Strip 3rd party header */
1034
1.07M
    if( tk->is_qnap )
1035
733
    {
1036
733
        if( p_frame->i_buffer >= QNAP_VIDEO_HEADER_SIZE )
1037
131
        {
1038
131
            const uint8_t *p = p_frame->p_buffer;
1039
            /* Check header is really there */
1040
131
            vlc_fourcc_t fcc = VLC_FOURCC(p[0],p[1],p[2],p[3]);
1041
            /* Parse QNAP header */
1042
131
            if( IsQNAPCodec(fcc) && p_sys->meta )
1043
3
            {
1044
3
                const char *psz_title = vlc_meta_Get( p_sys->meta, vlc_meta_Title );
1045
3
                char *psz_osd = (char *) &p_frame->p_buffer[24];
1046
3
                if( *psz_osd != 0 )
1047
2
                {
1048
2
                    psz_osd[23] = 0;
1049
2
                    if( !psz_title || strncmp( psz_osd, psz_title, 24 ) )
1050
2
                    {
1051
2
                        vlc_meta_Set( p_sys->meta, vlc_meta_Title, psz_osd );
1052
2
                        p_sys->updates |= INPUT_UPDATE_META;
1053
2
                    }
1054
2
                }
1055
3
            }
1056
131
            p_frame->i_buffer -= QNAP_VIDEO_HEADER_SIZE;
1057
131
            p_frame->p_buffer += QNAP_VIDEO_HEADER_SIZE;
1058
131
        }
1059
733
    }
1060
1061
1.07M
    if( tk->i_next_block_flags )
1062
0
    {
1063
0
        p_frame->i_flags = tk->i_next_block_flags;
1064
0
        tk->i_next_block_flags = 0;
1065
0
    }
1066
1067
1.07M
    if( tk->p_es )
1068
1.07M
        es_out_Send( p_demux->out, tk->p_es, p_frame );
1069
0
    else
1070
0
        block_Release( p_frame );
1071
1.07M
}
1072
1073
/*****************************************************************************
1074
 * Demux_Seekable: reads and demuxes data packets for stream seekable
1075
 *****************************************************************************
1076
 * AVIDemux: reads and demuxes data packets
1077
 *****************************************************************************
1078
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1079
 *****************************************************************************/
1080
static int Demux_Seekable( demux_t *p_demux )
1081
211M
{
1082
211M
    demux_sys_t *p_sys = p_demux->p_sys;
1083
1084
211M
    unsigned int i_track_count = 0;
1085
1086
    /* detect new selected/unselected streams */
1087
479M
    for( unsigned int i = 0; i < p_sys->i_track; i++ )
1088
268M
    {
1089
268M
        avi_track_t *tk = p_sys->track[i];
1090
268M
        bool  b = false;
1091
1092
268M
        es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
1093
268M
        if( tk->p_es_dv_audio )
1094
407
        {
1095
407
            bool b_extra = false;
1096
407
            es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es_dv_audio, &b_extra );
1097
407
            b |= b_extra;
1098
407
        }
1099
268M
        if( b && !tk->b_activated )
1100
0
        {
1101
0
            if( p_sys->b_seekable)
1102
0
            {
1103
0
                AVI_TrackSeek( p_demux, i, p_sys->i_time );
1104
0
            }
1105
0
            tk->b_activated = true;
1106
0
        }
1107
268M
        else if( !b && tk->b_activated )
1108
0
        {
1109
0
            tk->b_activated = false;
1110
0
        }
1111
268M
        if( b )
1112
268M
        {
1113
268M
            i_track_count++;
1114
268M
        }
1115
268M
    }
1116
1117
211M
    if( i_track_count <= 0 )
1118
0
    {
1119
0
        p_sys->i_time += p_sys->i_read_increment;
1120
0
        if( p_sys->i_length != 0 )
1121
0
        {
1122
0
            if( p_sys->i_time >= p_sys->i_length )
1123
0
                return VLC_DEMUXER_EOF;
1124
0
            return VLC_DEMUXER_SUCCESS;
1125
0
        }
1126
0
        msg_Warn( p_demux, "no track selected, exiting..." );
1127
0
        return VLC_DEMUXER_EOF;
1128
0
    }
1129
1130
    /* wait for the good time */
1131
211M
    es_out_SetPCR( p_demux->out, VLC_TICK_0 + p_sys->i_time );
1132
211M
    p_sys->i_time += p_sys->i_read_increment;
1133
1134
    /* init toread */
1135
479M
    for( unsigned i = 0; i < p_sys->i_track; i++ )
1136
268M
    {
1137
268M
        avi_track_t *tk = p_sys->track[i];
1138
1139
268M
        tk->demuxctx.b_ok = tk->b_activated && !tk->b_eof;
1140
268M
        if( tk->i_idxposc < tk->idx.i_size )
1141
216M
        {
1142
216M
            tk->demuxctx.i_posf = tk->idx.p_entry[tk->i_idxposc].i_pos;
1143
216M
           if( tk->i_idxposb > 0 )
1144
177M
           {
1145
177M
                tk->demuxctx.i_posf += 8 + tk->i_idxposb;
1146
177M
           }
1147
216M
        }
1148
51.9M
        else
1149
51.9M
        {
1150
51.9M
            tk->demuxctx.i_posf = -1;
1151
51.9M
        }
1152
1153
        /* Xsub specific. There's no possible chunk/byte<->time */
1154
268M
        if( tk->fmt.i_codec == FOURCC_DXSB )
1155
33.9k
        {
1156
            /* load spu times */
1157
33.9k
            if( tk->i_next_embedded_time == VLC_TICK_INVALID && tk->demuxctx.i_posf != -1 )
1158
8.65k
                tk->i_next_embedded_time = AVI_GetXsubSampleTimeAt(
1159
8.65k
                            p_demux->s, tk->idx.p_entry[ tk->i_idxposc].i_pos );
1160
33.9k
            vlc_tick_t i_reftime = tk->i_next_embedded_time != VLC_TICK_INVALID
1161
33.9k
                                 ? tk->i_next_embedded_time : tk->i_last_embedded_endtime;
1162
33.9k
            if( i_reftime != VLC_TICK_INVALID &&
1163
33.9k
                p_sys->i_time - i_reftime  >  VLC_TICK_FROM_SEC(-2) )
1164
0
                tk->demuxctx.i_toread = 1;
1165
33.9k
            else
1166
33.9k
                tk->demuxctx.i_toread = -1;
1167
33.9k
            continue;
1168
33.9k
        }
1169
1170
268M
        vlc_tick_t i_dpts = p_sys->i_time - AVI_GetPTS( tk );
1171
1172
268M
        if( tk->i_samplesize )
1173
245M
        {
1174
245M
            tk->demuxctx.i_toread = AVI_PTSToByte( tk, i_dpts );
1175
245M
        }
1176
23.3M
        else if ( i_dpts > VLC_TICK_FROM_SEC(-2) ) /* don't send a too early dts (low fps video) */
1177
23.3M
        {
1178
23.3M
            int64_t i_chunks_count = AVI_PTSToChunk( tk, i_dpts );
1179
23.3M
            if( i_dpts > 0 && AVI_GetDPTS( tk, i_chunks_count ) < i_dpts )
1180
22.6M
            {
1181
                /* AVI code is crap. toread is either bytes, or here, chunk count.
1182
                 * That does not even work when reading amount < scale / rate */
1183
22.6M
                i_chunks_count++;
1184
22.6M
            }
1185
23.3M
            tk->demuxctx.i_toread = i_chunks_count;
1186
23.3M
        }
1187
36.9k
        else
1188
36.9k
            tk->demuxctx.i_toread = -1;
1189
268M
    }
1190
1191
211M
    for( ;; )
1192
227M
    {
1193
227M
        bool b_done = true;
1194
227M
        block_t         *p_frame;
1195
227M
        int64_t i_pos = -1;
1196
227M
        unsigned int i_track = 0;
1197
1198
        /* search for first chunk to be read */
1199
530M
        for( unsigned i = 0; i < p_sys->i_track; i++ )
1200
302M
        {
1201
302M
            avi_track_t *tk = p_sys->track[i];
1202
302M
            if( !tk->demuxctx.b_ok ||
1203
302M
                ( p_sys->b_fastseekable && p_sys->b_interleaved &&
1204
254M
                  AVI_GetDPTS( tk, tk->demuxctx.i_toread ) <= -p_sys->i_read_increment ) )
1205
57.8M
            {
1206
57.8M
                continue;
1207
57.8M
            }
1208
1209
244M
            if( tk->demuxctx.i_toread > 0 )
1210
38.1M
            {
1211
38.1M
                b_done = false; /* not yet finished */
1212
1213
38.1M
                if( tk->demuxctx.i_posf > 0 )
1214
16.9M
                {
1215
16.9M
                    if( i_pos == -1 || i_pos > tk->demuxctx.i_posf )
1216
16.9M
                    {
1217
16.9M
                        i_track = i;
1218
16.9M
                        i_pos = tk->demuxctx.i_posf;
1219
16.9M
                    }
1220
16.9M
                }
1221
38.1M
            }
1222
244M
        }
1223
1224
227M
        if( b_done )
1225
191M
        {
1226
198M
            for( unsigned i = 0; i < p_sys->i_track; i++ )
1227
198M
            {
1228
198M
                const avi_track_t *tk = p_sys->track[i];
1229
198M
                if( tk->demuxctx.b_ok && tk->demuxctx.i_toread >= 0 )
1230
191M
                    return VLC_DEMUXER_SUCCESS;
1231
198M
            }
1232
2.09k
            msg_Warn( p_demux, "all tracks have failed, exiting..." );
1233
2.09k
            return VLC_DEMUXER_EOF;
1234
191M
        }
1235
1236
36.0M
        if( i_pos == -1 )
1237
19.1M
        {
1238
19.1M
            unsigned short i_loop_count = 0;
1239
1240
            /* no valid index, we will parse directly the stream
1241
             * in case we fail we will disable all finished stream */
1242
19.1M
            if( p_sys->b_seekable && p_sys->i_movi_lastchunk_pos >= p_sys->i_movi_begin + 12 )
1243
18.8M
            {
1244
18.8M
                if (vlc_stream_Seek(p_demux->s, p_sys->i_movi_lastchunk_pos))
1245
0
                    return VLC_DEMUXER_EGENERIC;
1246
1247
18.8M
                if( AVI_PacketNext( p_demux ) )
1248
18.5M
                {
1249
18.5M
                    return( AVI_TrackStopFinishedStreams( p_demux ) ? 0 : 1 );
1250
18.5M
                }
1251
18.8M
            }
1252
315k
            else
1253
315k
            {
1254
315k
                if (vlc_stream_Seek(p_demux->s, p_sys->i_movi_begin + 12))
1255
0
                    return VLC_DEMUXER_EGENERIC;
1256
315k
            }
1257
1258
623k
            for( ;; )
1259
827k
            {
1260
827k
                avi_packet_t avi_pk;
1261
1262
827k
                if( AVI_PacketGetHeader( p_demux, &avi_pk ) )
1263
128k
                {
1264
128k
                    msg_Warn( p_demux,
1265
128k
                             "cannot get packet header, track disabled" );
1266
128k
                    return( AVI_TrackStopFinishedStreams( p_demux ) ? 0 : 1 );
1267
128k
                }
1268
699k
                if( avi_pk.i_stream >= p_sys->i_track ||
1269
699k
                    ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
1270
687k
                {
1271
687k
                    if( AVI_PacketNext( p_demux ) )
1272
485k
                    {
1273
485k
                        msg_Warn( p_demux,
1274
485k
                                  "cannot skip packet, track disabled" );
1275
485k
                        return( AVI_TrackStopFinishedStreams( p_demux ) ? 0 : 1 );
1276
485k
                    }
1277
1278
201k
                    if( !++i_loop_count )
1279
201k
                         msg_Warn( p_demux, "don't seem to find any data..." );
1280
201k
                    continue;
1281
687k
                }
1282
12.2k
                else
1283
12.2k
                {
1284
12.2k
                    i_track = avi_pk.i_stream;
1285
12.2k
                    avi_track_t *tk = p_sys->track[i_track];
1286
1287
                    /* add this chunk to the index */
1288
12.2k
                    avi_entry_t index;
1289
12.2k
                    index.i_flags  = AVI_GetKeyFlag(tk, avi_pk.i_peek);
1290
12.2k
                    index.i_pos    = avi_pk.i_pos;
1291
12.2k
                    index.i_length = avi_pk.i_size;
1292
12.2k
                    index.i_lengthtotal = index.i_length;
1293
12.2k
                    int64_t i_indexid = avi_index_Append( &tk->idx, &p_sys->i_movi_lastchunk_pos, &index );
1294
1295
                    /* do we will read this data ? */
1296
12.2k
                    if( i_indexid >= 0 &&
1297
12.2k
                        AVI_GetDPTS( tk, tk->demuxctx.i_toread ) > -p_sys->i_read_increment )
1298
10.5k
                    {
1299
10.5k
                        tk->i_idxposc = (unsigned int) i_indexid;
1300
10.5k
                        tk->i_idxposb = 0;
1301
10.5k
                        break;
1302
10.5k
                    }
1303
1.73k
                    else
1304
1.73k
                    {
1305
1.73k
                        if( AVI_PacketNext( p_demux ) )
1306
83
                        {
1307
83
                            msg_Warn( p_demux,
1308
83
                                      "cannot skip packet, track disabled" );
1309
83
                            return( AVI_TrackStopFinishedStreams( p_demux ) ? 0 : 1 );
1310
83
                        }
1311
1.73k
                    }
1312
12.2k
                }
1313
699k
            }
1314
1315
623k
        }
1316
16.8M
        else
1317
16.8M
        {
1318
16.8M
            if (vlc_stream_Seek(p_demux->s, i_pos))
1319
0
                return VLC_DEMUXER_EGENERIC;
1320
16.8M
        }
1321
1322
        /* Set the track to use */
1323
16.8M
        avi_track_t *tk = p_sys->track[i_track];
1324
1325
16.8M
        size_t i_size;
1326
16.8M
        unsigned i_ck_remaining_bytes = tk->idx.p_entry[tk->i_idxposc].i_length -
1327
16.8M
                                        tk->i_idxposb;
1328
1329
        /* read those data */
1330
16.8M
        if( tk->i_samplesize )
1331
7.38M
        {
1332
7.38M
            int64_t i_toread;
1333
1334
            /* remaining bytes to read inside the current read increment */
1335
7.38M
            if( ( i_toread = tk->demuxctx.i_toread ) <= 0 )
1336
697
            {
1337
697
                if( tk->i_samplesize > 1 )
1338
559
                {
1339
559
                    i_toread = tk->i_samplesize;
1340
559
                }
1341
138
                else
1342
138
                {
1343
                    /* refill current read increment */
1344
138
                    i_toread = AVI_PTSToByte( tk, VLC_TICK_FROM_MS(20) );
1345
138
                    i_toread = __MAX( i_toread, 100 );
1346
138
                }
1347
697
            }
1348
7.38M
            i_size = __MIN( i_ck_remaining_bytes, (size_t) i_toread );
1349
7.38M
        }
1350
9.48M
        else
1351
9.48M
        {
1352
9.48M
            assert(tk->i_idxposb == 0);
1353
9.48M
            i_size = i_ck_remaining_bytes;
1354
9.48M
        }
1355
1356
        /* need to read and skip tag/header */
1357
16.8M
        const uint8_t i_header = ( tk->i_idxposb == 0 ) ? 8 : 0;
1358
1359
16.8M
        if( ( p_frame = ReadFrame( p_demux, tk, i_header, i_size ) )==NULL )
1360
15.7M
        {
1361
15.7M
            msg_Warn( p_demux, "failed reading data" );
1362
15.7M
            tk->b_eof = false;
1363
15.7M
            tk->demuxctx.b_ok = false;
1364
15.7M
            continue;
1365
15.7M
        }
1366
1367
1.07M
        if( p_frame->i_pts == VLC_TICK_INVALID )
1368
1.07M
            p_frame->i_pts = VLC_TICK_0 + AVI_GetPTS( tk );
1369
0
        else
1370
0
            tk->i_last_embedded_endtime = p_frame->i_pts + p_frame->i_length;
1371
1372
1.07M
        if( tk->idx.p_entry[tk->i_idxposc].i_flags&AVIIF_KEYFRAME )
1373
1.06M
        {
1374
1.06M
            p_frame->i_flags = BLOCK_FLAG_TYPE_I;
1375
1.06M
        }
1376
9.69k
        else if( tk->fmt.i_cat == VIDEO_ES )
1377
1.33k
        {
1378
1.33k
            p_frame->i_flags = BLOCK_FLAG_TYPE_PB;
1379
1.33k
        }
1380
1381
        /* advance chunk/byte pointers */
1382
1.07M
        if( tk->i_samplesize )
1383
1.06M
        {
1384
1.06M
            tk->demuxctx.i_toread -= i_size;
1385
1.06M
            tk->i_idxposb += i_size;
1386
1.06M
            if( tk->i_idxposb >=
1387
1.06M
                    tk->idx.p_entry[tk->i_idxposc].i_length )
1388
2.54k
            {
1389
2.54k
                tk->i_idxposb = 0;
1390
2.54k
                tk->i_idxposc++;
1391
2.54k
            }
1392
1.06M
        }
1393
9.10k
        else /* full chunk */
1394
9.10k
        {
1395
            /* Goto to next chunk */
1396
9.10k
            tk->i_idxposc++;
1397
9.10k
            if( tk->fmt.i_cat == AUDIO_ES )
1398
1.29k
            {
1399
1.29k
                tk->i_blockno += tk->i_blocksize > 0 ? ( i_size + tk->i_blocksize - 1 ) / tk->i_blocksize : 1;
1400
1.29k
            }
1401
7.81k
            else if( tk->fmt.i_cat == SPU_ES )
1402
265
            {
1403
265
                tk->i_next_embedded_time = VLC_TICK_INVALID;
1404
265
            }
1405
9.10k
            tk->demuxctx.i_toread--;
1406
9.10k
        }
1407
1408
        /* check new chunk and set new read pos */
1409
1.07M
        if( tk->i_idxposc < tk->idx.i_size)
1410
1.06M
        {
1411
1.06M
            tk->demuxctx.i_posf =
1412
1.06M
                tk->idx.p_entry[tk->i_idxposc].i_pos;
1413
1.06M
            if( tk->i_idxposb > 0 )
1414
1.06M
            {
1415
1.06M
                tk->demuxctx.i_posf += 8 + tk->i_idxposb;
1416
1.06M
            }
1417
1418
1.06M
        }
1419
9.66k
        else /* all chunks read for this track */
1420
9.66k
        {
1421
9.66k
            tk->demuxctx.i_posf = -1;
1422
9.66k
        }
1423
1424
1.07M
        AVI_SendFrame( p_demux, tk, p_frame );
1425
1.07M
    }
1426
211M
}
1427
1428
1429
/*****************************************************************************
1430
 * Demux_UnSeekable: reads and demuxes data packets for unseekable file
1431
 *****************************************************************************
1432
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
1433
 *****************************************************************************/
1434
static int Demux_UnSeekable( demux_t *p_demux )
1435
0
{
1436
0
    demux_sys_t     *p_sys = p_demux->p_sys;
1437
0
    avi_track_t *p_stream_master = NULL;
1438
0
    unsigned int i_stream;
1439
0
    unsigned int i_packet;
1440
1441
0
    es_out_SetPCR( p_demux->out, VLC_TICK_0 + p_sys->i_time );
1442
1443
    /* *** find master stream for data packet skipping algo *** */
1444
    /* *** -> first video, if any, or first audio ES *** */
1445
0
    for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
1446
0
    {
1447
0
        avi_track_t *tk = p_sys->track[i_stream];
1448
0
        bool  b;
1449
1450
0
        es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
1451
0
        if( tk->p_es_dv_audio )
1452
0
        {
1453
0
            bool b_extra;
1454
0
            es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es_dv_audio, &b_extra );
1455
0
            b |= b_extra;
1456
0
        }
1457
1458
0
        if( b )
1459
0
        {
1460
0
            if( tk->fmt.i_cat == VIDEO_ES )
1461
0
            {
1462
0
                p_stream_master = tk;
1463
0
                break;
1464
0
            }
1465
0
            else if( !p_stream_master )
1466
0
            {
1467
0
                p_stream_master = tk;
1468
0
            }
1469
0
        }
1470
0
    }
1471
1472
0
    if( !p_stream_master )
1473
0
    {
1474
0
        if( p_sys->i_track )
1475
0
        {
1476
0
            p_stream_master = p_sys->track[0];
1477
0
        }
1478
0
        else
1479
0
        {
1480
0
            msg_Warn( p_demux, "no more stream selected" );
1481
0
            return VLC_DEMUXER_EOF;
1482
0
        }
1483
0
    }
1484
1485
0
    p_sys->i_time = AVI_GetPTS( p_stream_master );
1486
1487
0
    for( i_packet = 0; i_packet < 10; i_packet++)
1488
0
    {
1489
0
        avi_packet_t    avi_pk;
1490
1491
0
        if( AVI_PacketGetHeader( p_demux, &avi_pk ) )
1492
0
        {
1493
0
            return VLC_DEMUXER_EOF;
1494
0
        }
1495
1496
0
        if( avi_pk.i_stream >= p_sys->i_track ||
1497
0
            ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
1498
0
        {
1499
            /* we haven't found an audio or video packet:
1500
             *  - we have seek, found first next packet
1501
             *  - others packets could be found, skip them
1502
             */
1503
0
            switch( avi_pk.i_fourcc )
1504
0
            {
1505
0
                case AVIFOURCC_JUNK:
1506
0
                case AVIFOURCC_LIST:
1507
0
                case AVIFOURCC_RIFF:
1508
0
                    return( !AVI_PacketNext( p_demux ) ? 1 : 0 );
1509
0
                case AVIFOURCC_idx1:
1510
0
                    if( p_sys->b_odml )
1511
0
                    {
1512
0
                        return( !AVI_PacketNext( p_demux ) ? 1 : 0 );
1513
0
                    }
1514
0
                    return VLC_DEMUXER_EOF;
1515
0
                default:
1516
0
                    msg_Warn( p_demux,
1517
0
                              "seems to have lost position @%"PRIu64", resync",
1518
0
                              vlc_stream_Tell(p_demux->s) );
1519
0
                    if( AVI_PacketSearch( p_demux ) )
1520
0
                    {
1521
0
                        msg_Err( p_demux, "resync failed" );
1522
0
                        return VLC_DEMUXER_EGENERIC;
1523
0
                    }
1524
0
            }
1525
0
        }
1526
0
        else
1527
0
        {
1528
0
            avi_track_t *p_stream = p_sys->track[avi_pk.i_stream];
1529
            /* check for time */
1530
0
            if( p_stream == p_stream_master ||
1531
0
                llabs( AVI_GetPTS( p_stream ) -
1532
0
                        AVI_GetPTS( p_stream_master ) )< VLC_TICK_FROM_SEC(2) )
1533
0
            {
1534
                /* load it and send to decoder */
1535
0
                block_t *p_frame = ReadFrame( p_demux, p_stream, 8, avi_pk.i_size ) ;
1536
0
                if( p_frame == NULL )
1537
0
                {
1538
0
                    return VLC_DEMUXER_EGENERIC;
1539
0
                }
1540
1541
0
                if( p_frame->i_pts == VLC_TICK_INVALID )
1542
0
                    p_frame->i_pts = VLC_TICK_0 + AVI_GetPTS( p_stream );
1543
0
                else
1544
0
                    p_stream->i_last_embedded_endtime = p_frame->i_pts + p_frame->i_length;
1545
1546
0
                AVI_SendFrame( p_demux, p_stream, p_frame );
1547
0
            }
1548
0
            else
1549
0
            {
1550
0
                if( AVI_PacketNext( p_demux ) )
1551
0
                {
1552
0
                    return VLC_DEMUXER_EOF;
1553
0
                }
1554
0
            }
1555
1556
            /* *** update stream time position *** */
1557
0
            if( p_stream->i_samplesize )
1558
0
            {
1559
0
                p_stream->i_idxposb += avi_pk.i_size;
1560
0
            }
1561
0
            else
1562
0
            {
1563
0
                if( p_stream->fmt.i_cat == AUDIO_ES )
1564
0
                {
1565
0
                    p_stream->i_blockno += p_stream->i_blocksize > 0 ? ( avi_pk.i_size + p_stream->i_blocksize - 1 ) / p_stream->i_blocksize : 1;
1566
0
                }
1567
0
                p_stream->i_idxposc++;
1568
0
                p_stream->i_next_embedded_time = VLC_TICK_INVALID;
1569
0
            }
1570
1571
0
        }
1572
0
    }
1573
1574
0
    return VLC_DEMUXER_SUCCESS;
1575
0
}
1576
1577
/*****************************************************************************
1578
 * Seek: goto to i_date or i_percent
1579
 *****************************************************************************/
1580
static int Seek( demux_t *p_demux, vlc_tick_t i_date, double f_ratio, bool b_accurate )
1581
0
{
1582
0
    demux_sys_t *p_sys = p_demux->p_sys;
1583
0
    msg_Dbg( p_demux, "seek requested: %"PRId64" seconds %2.2f%%",
1584
0
             SEC_FROM_VLC_TICK(i_date), f_ratio * 100 );
1585
1586
0
    if( p_sys->b_seekable )
1587
0
    {
1588
0
        uint64_t i_pos_backup = vlc_stream_Tell( p_demux->s );
1589
1590
        /* Check and lazy load indexes if it was not done (not fastseekable) */
1591
0
        if ( !p_sys->b_indexloaded && ( p_sys->i_avih_flags & AVIF_HASINDEX ) )
1592
0
        {
1593
0
            avi_chunk_t *p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0, true );
1594
0
            if (unlikely( !p_riff ))
1595
0
                return VLC_EGENERIC;
1596
1597
0
            int i_ret = AVI_ChunkFetchIndexes( p_demux->s, p_riff );
1598
0
            if ( i_ret )
1599
0
            {
1600
                /* Go back to position before index failure */
1601
0
                if (vlc_stream_Tell(p_demux->s) != i_pos_backup
1602
0
                 && vlc_stream_Seek(p_demux->s, i_pos_backup))
1603
0
                    return VLC_EGENERIC;
1604
1605
0
                if ( p_sys->i_avih_flags & AVIF_MUSTUSEINDEX )
1606
0
                    return VLC_EGENERIC;
1607
0
            }
1608
0
            else AVI_IndexLoad( p_demux );
1609
1610
0
            p_sys->b_indexloaded = true; /* we don't want to try each time */
1611
0
        }
1612
1613
0
        if( p_sys->i_length == 0 )
1614
0
        {
1615
0
            avi_track_t *p_stream = NULL;
1616
0
            uint64_t i_pos;
1617
1618
0
            if ( !p_sys->i_movi_lastchunk_pos && /* set when index is successfully loaded */
1619
0
                 ! ( p_sys->i_avih_flags & AVIF_ISINTERLEAVED ) )
1620
0
            {
1621
0
                msg_Warn( p_demux, "seeking without index at %2.2f%%"
1622
0
                         " only works for interleaved files", f_ratio * 100 );
1623
0
                goto failandresetpos;
1624
0
            }
1625
            /* use i_percent to create a true i_date */
1626
0
            if( f_ratio >= 1.0 )
1627
0
            {
1628
0
                msg_Warn( p_demux, "cannot seek so far !" );
1629
0
                goto failandresetpos;
1630
0
            }
1631
0
            f_ratio = __MAX( f_ratio, 0 );
1632
1633
            /* try to find chunk that is at i_percent or the file */
1634
0
            i_pos = __MAX( f_ratio * stream_Size( p_demux->s ),
1635
0
                           p_sys->i_movi_begin );
1636
            /* search first selected stream (and prefer non-EOF ones) */
1637
0
            for( unsigned i = 0; i < p_sys->i_track; i++ )
1638
0
            {
1639
0
                avi_track_t *p_track = p_sys->track[i];
1640
0
                if( !p_track->b_activated || p_track->fmt.i_cat == SPU_ES )
1641
0
                    continue;
1642
1643
0
                p_stream = p_track;
1644
0
                if( !p_track->b_eof )
1645
0
                    break;
1646
0
            }
1647
0
            if( p_stream == NULL )
1648
0
            {
1649
0
                msg_Warn( p_demux, "cannot find any selected stream" );
1650
0
                goto failandresetpos;
1651
0
            }
1652
1653
            /* be sure that the index exist */
1654
0
            if( AVI_StreamChunkSet( p_demux, p_stream, 0 ) )
1655
0
            {
1656
0
                msg_Warn( p_demux, "cannot seek" );
1657
0
                goto failandresetpos;
1658
0
            }
1659
1660
0
            while( i_pos >= p_stream->idx.p_entry[p_stream->i_idxposc].i_pos +
1661
0
               p_stream->idx.p_entry[p_stream->i_idxposc].i_length + 8 )
1662
0
            {
1663
                /* search after i_idxposc */
1664
0
                if( AVI_StreamChunkSet( p_demux,
1665
0
                                        p_stream, p_stream->i_idxposc + 1 ) )
1666
0
                {
1667
0
                    msg_Warn( p_demux, "cannot seek" );
1668
0
                    goto failandresetpos;
1669
0
                }
1670
0
            }
1671
1672
0
            i_date = AVI_GetPTS( p_stream );
1673
            /* TODO better support for i_samplesize != 0 */
1674
0
            msg_Dbg( p_demux, "estimate date %"PRId64, i_date );
1675
0
        }
1676
1677
        /* */
1678
0
        vlc_tick_t i_wanted = i_date;
1679
0
        vlc_tick_t i_start = i_date;
1680
        /* Do a 2 pass seek, first with video (can seek ahead due to keyframes),
1681
           so we can seek audio to the same starting time */
1682
0
        for(int i=0; i<2; i++)
1683
0
        {
1684
0
            for( unsigned i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
1685
0
            {
1686
0
                avi_track_t *p_stream = p_sys->track[i_stream];
1687
1688
0
                if( !p_stream->b_activated )
1689
0
                    continue;
1690
1691
0
                if( (i==0 && p_stream->fmt.i_cat != VIDEO_ES) ||
1692
0
                    (i!=0 && p_stream->fmt.i_cat == VIDEO_ES) )
1693
0
                    continue;
1694
1695
0
                p_stream->b_eof = AVI_TrackSeek( p_demux, i_stream, i_wanted ) != 0;
1696
0
                if( !p_stream->b_eof )
1697
0
                {
1698
0
                    p_stream->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY;
1699
1700
0
                    if( p_stream->fmt.i_cat == AUDIO_ES || p_stream->fmt.i_cat == VIDEO_ES )
1701
0
                        i_start = __MIN(i_start, AVI_GetPTS( p_stream ));
1702
1703
0
                    if( i == 0 && p_stream->fmt.i_cat == VIDEO_ES )
1704
0
                        i_wanted = i_start;
1705
0
                }
1706
0
            }
1707
0
        }
1708
0
        p_sys->i_time = i_start;
1709
0
        es_out_SetPCR( p_demux->out, VLC_TICK_0 + p_sys->i_time );
1710
0
        if( b_accurate )
1711
0
            es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, VLC_TICK_0 + i_date );
1712
0
        msg_Dbg( p_demux, "seek: %"PRId64" seconds", SEC_FROM_VLC_TICK(p_sys->i_time) );
1713
0
        return VLC_SUCCESS;
1714
1715
0
failandresetpos:
1716
        /* Go back to position before index failure */
1717
0
        if ( vlc_stream_Tell( p_demux->s ) - i_pos_backup )
1718
0
            vlc_stream_Seek( p_demux->s, i_pos_backup );
1719
1720
0
        return VLC_EGENERIC;
1721
0
    }
1722
0
    else
1723
0
    {
1724
0
        msg_Err( p_demux, "shouldn't yet be executed" );
1725
0
        return VLC_EGENERIC;
1726
0
    }
1727
0
}
1728
1729
/*****************************************************************************
1730
 * Control:
1731
 *****************************************************************************/
1732
static double ControlGetPosition( demux_t *p_demux )
1733
0
{
1734
0
    demux_sys_t *p_sys = p_demux->p_sys;
1735
1736
0
    if( p_sys->i_length != 0 )
1737
0
    {
1738
0
        return (double)p_sys->i_time / (double)p_sys->i_length;
1739
0
    }
1740
0
    else if( stream_Size( p_demux->s ) > 0 )
1741
0
    {
1742
0
        double i64 = (uint64_t)vlc_stream_Tell( p_demux->s );
1743
0
        return i64 / stream_Size( p_demux->s );
1744
0
    }
1745
0
    return 0.0;
1746
0
}
1747
1748
static int Control( demux_t *p_demux, int i_query, va_list args )
1749
0
{
1750
0
    demux_sys_t *p_sys = p_demux->p_sys;
1751
0
    double   f, *pf;
1752
0
    vlc_tick_t i64;
1753
0
    bool b;
1754
0
    vlc_meta_t *p_meta;
1755
1756
0
    switch( i_query )
1757
0
    {
1758
0
        case DEMUX_CAN_SEEK:
1759
0
            *va_arg( args, bool * ) = p_sys->b_seekable;
1760
0
            return VLC_SUCCESS;
1761
1762
0
        case DEMUX_GET_POSITION:
1763
0
            pf = va_arg( args, double * );
1764
0
            *pf = ControlGetPosition( p_demux );
1765
0
            return VLC_SUCCESS;
1766
0
        case DEMUX_SET_POSITION:
1767
0
            f = va_arg( args, double );
1768
0
            b = va_arg( args, int );
1769
0
            if ( !p_sys->b_seekable )
1770
0
            {
1771
0
                return VLC_EGENERIC;
1772
0
            }
1773
0
            else
1774
0
            {
1775
0
                i64 = f * p_sys->i_length;
1776
0
                return Seek( p_demux, i64, f, b );
1777
0
            }
1778
1779
0
        case DEMUX_GET_TIME:
1780
0
            *va_arg( args, vlc_tick_t * ) = p_sys->i_time;
1781
0
            return VLC_SUCCESS;
1782
1783
0
        case DEMUX_SET_TIME:
1784
0
        {
1785
0
            f = 0;
1786
1787
0
            i64 = va_arg( args, vlc_tick_t );
1788
0
            b = va_arg( args, int );
1789
0
            if( !p_sys->b_seekable )
1790
0
            {
1791
0
                return VLC_EGENERIC;
1792
0
            }
1793
0
            else if( p_sys->i_length != 0 )
1794
0
            {
1795
0
                f = (double)i64 / p_sys->i_length;
1796
0
            }
1797
0
            else if( p_sys->i_time > 0 )
1798
0
            {
1799
0
                f = ControlGetPosition( p_demux ) *
1800
0
                   (double) i64 / (double)p_sys->i_time;
1801
0
            }
1802
0
            return Seek( p_demux, i64, f, b );
1803
0
        }
1804
0
        case DEMUX_GET_LENGTH:
1805
0
            *va_arg( args, vlc_tick_t * ) = p_sys->i_length;
1806
0
            return VLC_SUCCESS;
1807
1808
0
        case DEMUX_GET_FPS:
1809
0
            pf = va_arg( args, double * );
1810
0
            *pf = 0.0;
1811
0
            for( unsigned i = 0; i < p_sys->i_track; i++ )
1812
0
            {
1813
0
                avi_track_t *tk = p_sys->track[i];
1814
0
                if( tk->fmt.i_cat == VIDEO_ES && tk->i_scale > 0)
1815
0
                {
1816
0
                    *pf = (float)tk->i_rate / (float)tk->i_scale;
1817
0
                    break;
1818
0
                }
1819
0
            }
1820
0
            return VLC_SUCCESS;
1821
1822
0
        case DEMUX_GET_META:
1823
0
            p_meta = va_arg( args, vlc_meta_t * );
1824
0
            vlc_meta_Merge( p_meta,  p_sys->meta );
1825
0
            return VLC_SUCCESS;
1826
1827
0
        case DEMUX_GET_ATTACHMENTS:
1828
0
        {
1829
0
            if( p_sys->i_attachment <= 0 )
1830
0
                return VLC_EGENERIC;
1831
1832
0
            input_attachment_t ***ppp_attach = va_arg( args, input_attachment_t*** );
1833
0
            int *pi_int = va_arg( args, int * );
1834
1835
0
            *ppp_attach = calloc( p_sys->i_attachment, sizeof(**ppp_attach) );
1836
0
            if( likely(*ppp_attach) )
1837
0
            {
1838
0
                *pi_int = p_sys->i_attachment;
1839
0
                for( unsigned i = 0; i < p_sys->i_attachment; i++ )
1840
0
                    (*ppp_attach)[i] = vlc_input_attachment_Hold( p_sys->attachment[i] );
1841
0
                return VLC_SUCCESS;
1842
0
            }
1843
0
            return VLC_EGENERIC;
1844
0
        }
1845
1846
0
        case DEMUX_TEST_AND_CLEAR_FLAGS:
1847
0
        {
1848
0
            unsigned *restrict flags = va_arg( args, unsigned * );
1849
0
            *flags &= p_sys->updates;
1850
0
            p_sys->updates &= ~*flags;
1851
0
            return VLC_SUCCESS;
1852
0
        }
1853
1854
0
        case DEMUX_CAN_PAUSE:
1855
0
        case DEMUX_SET_PAUSE_STATE:
1856
0
        case DEMUX_CAN_CONTROL_PACE:
1857
0
        case DEMUX_GET_PTS_DELAY:
1858
0
            return demux_vaControlHelper( p_demux->s, 0, -1, 0, 1, i_query, args );
1859
1860
0
        default:
1861
0
            return VLC_EGENERIC;
1862
0
    }
1863
0
}
1864
1865
/*****************************************************************************
1866
 * Function to convert pts to chunk or byte
1867
 *****************************************************************************/
1868
1869
static int64_t AVI_Rescale( vlc_tick_t i_value, uint32_t i_timescale, uint32_t i_newscale )
1870
784M
{
1871
    /* TODO: replace (and mp4) with better global helper (recursive checks) */
1872
784M
    if( i_timescale == i_newscale )
1873
492k
        return i_value;
1874
1875
784M
    if( (i_value >= 0 && i_value <= VLC_TICK_MAX / i_newscale) ||
1876
784M
        (i_value < 0  && i_value >= VLC_TICK_MIN / i_newscale) )
1877
665M
        return i_value * i_newscale / i_timescale;
1878
1879
    /* overflow */
1880
118M
    int64_t q = i_value / i_timescale;
1881
118M
    int64_t r = i_value % i_timescale;
1882
118M
    return q * i_newscale + r * i_newscale / i_timescale;
1883
784M
}
1884
1885
static int64_t AVI_PTSToChunk( avi_track_t *tk, vlc_tick_t i_pts )
1886
23.3M
{
1887
23.3M
    if( !tk->i_scale )
1888
0
        return 0;
1889
1890
23.3M
    i_pts = AVI_Rescale( i_pts, tk->i_scale, tk->i_rate );
1891
23.3M
    return SEC_FROM_VLC_TICK(i_pts);
1892
23.3M
}
1893
1894
static int64_t AVI_PTSToByte( avi_track_t *tk, vlc_tick_t i_pts )
1895
245M
{
1896
245M
    if( !tk->i_scale || !tk->i_samplesize )
1897
0
        return 0;
1898
1899
245M
    i_pts = AVI_Rescale( i_pts, tk->i_scale, tk->i_rate );
1900
245M
    return samples_from_vlc_tick( i_pts, tk->i_samplesize );
1901
245M
}
1902
1903
static vlc_tick_t AVI_GetDPTS( avi_track_t *tk, int64_t i_count )
1904
516M
{
1905
516M
    vlc_tick_t i_dpts = 0;
1906
1907
516M
    if( !tk->i_rate )
1908
27.7k
        return 0;
1909
1910
516M
    if( !tk->i_scale )
1911
6.93k
        return 0;
1912
1913
516M
    i_dpts = AVI_Rescale( CLOCK_FREQ * i_count, tk->i_rate, tk->i_scale );
1914
1915
516M
    if( tk->i_samplesize )
1916
459M
    {
1917
459M
        return i_dpts / tk->i_samplesize;
1918
459M
    }
1919
56.7M
    return i_dpts;
1920
516M
}
1921
1922
static vlc_tick_t AVI_GetPTS( avi_track_t *tk )
1923
269M
{
1924
    /* Lookup samples index */
1925
269M
    if( tk->i_samplesize && tk->idx.i_size )
1926
207M
    {
1927
207M
        int64_t i_count = 0;
1928
207M
        unsigned int idx = tk->i_idxposc;
1929
1930
        /* we need a valid entry we will emulate one */
1931
207M
        if( idx >= tk->idx.i_size )
1932
1.30M
        {
1933
            /* use the last entry */
1934
1.30M
            idx = tk->idx.i_size - 1;
1935
1.30M
            i_count = tk->idx.p_entry[idx].i_lengthtotal
1936
1.30M
                    + tk->idx.p_entry[idx].i_length;
1937
1.30M
        }
1938
206M
        else
1939
206M
        {
1940
206M
            i_count = tk->idx.p_entry[idx].i_lengthtotal;
1941
206M
        }
1942
207M
        return AVI_GetDPTS( tk, i_count + tk->i_idxposb );
1943
207M
    }
1944
1945
61.6M
    if( tk->fmt.i_cat == AUDIO_ES )
1946
60.0M
        return AVI_GetDPTS( tk, tk->i_blockno );
1947
1.62M
    else
1948
1.62M
        return AVI_GetDPTS( tk, tk->i_idxposc );
1949
61.6M
}
1950
1951
static int AVI_StreamChunkFind( demux_t *p_demux, avi_track_t *tk )
1952
0
{
1953
0
    demux_sys_t *p_sys = p_demux->p_sys;
1954
0
    avi_packet_t avi_pk;
1955
0
    unsigned short i_loop_count = 0;
1956
1957
    /* find first chunk of i_stream that isn't in index */
1958
1959
0
    if( p_sys->i_movi_lastchunk_pos >= p_sys->i_movi_begin + 12 )
1960
0
    {
1961
0
        if (vlc_stream_Seek(p_demux->s, p_sys->i_movi_lastchunk_pos))
1962
0
            return VLC_EGENERIC;
1963
0
        if( AVI_PacketNext( p_demux ) )
1964
0
        {
1965
0
            return VLC_EGENERIC;
1966
0
        }
1967
0
    }
1968
0
    else
1969
0
    {
1970
0
        if (vlc_stream_Seek(p_demux->s, p_sys->i_movi_begin + 12))
1971
0
            return VLC_EGENERIC;
1972
0
    }
1973
1974
0
    for( ;; )
1975
0
    {
1976
0
        if( AVI_PacketGetHeader( p_demux, &avi_pk ) )
1977
0
        {
1978
0
            msg_Warn( p_demux, "cannot get packet header" );
1979
0
            return VLC_EGENERIC;
1980
0
        }
1981
0
        if( avi_pk.i_stream >= p_sys->i_track ||
1982
0
            ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
1983
0
        {
1984
0
            if( AVI_PacketNext( p_demux ) )
1985
0
            {
1986
0
                return VLC_EGENERIC;
1987
0
            }
1988
1989
0
            if( !++i_loop_count )
1990
0
                 msg_Warn( p_demux, "don't seem to find any data..." );
1991
0
        }
1992
0
        else
1993
0
        {
1994
0
            avi_track_t *tk_pk = p_sys->track[avi_pk.i_stream];
1995
1996
            /* add this chunk to the index */
1997
0
            avi_entry_t index;
1998
0
            index.i_flags  = AVI_GetKeyFlag(tk_pk, avi_pk.i_peek);
1999
0
            index.i_pos    = avi_pk.i_pos;
2000
0
            index.i_length = avi_pk.i_size;
2001
0
            index.i_lengthtotal = index.i_length;
2002
0
            avi_index_Append( &tk_pk->idx, &p_sys->i_movi_lastchunk_pos, &index );
2003
2004
0
            if( tk_pk == tk )
2005
0
            {
2006
0
                return VLC_SUCCESS;
2007
0
            }
2008
2009
0
            if( AVI_PacketNext( p_demux ) )
2010
0
            {
2011
0
                return VLC_EGENERIC;
2012
0
            }
2013
0
        }
2014
0
    }
2015
0
}
2016
2017
/* be sure that i_ck will be a valid index entry */
2018
static int AVI_StreamChunkSet( demux_t *p_demux, avi_track_t *p_stream,
2019
                               unsigned int i_ck )
2020
0
{
2021
0
    p_stream->i_idxposc = i_ck;
2022
0
    p_stream->i_idxposb = 0;
2023
2024
0
    if(  i_ck >= p_stream->idx.i_size )
2025
0
    {
2026
0
        p_stream->i_idxposc = p_stream->idx.i_size - 1;
2027
0
        do
2028
0
        {
2029
0
            p_stream->i_idxposc++;
2030
0
            if( AVI_StreamChunkFind( p_demux, p_stream ) )
2031
0
            {
2032
0
                return VLC_EGENERIC;
2033
0
            }
2034
2035
0
        } while( p_stream->i_idxposc < i_ck );
2036
0
    }
2037
2038
0
    return VLC_SUCCESS;
2039
0
}
2040
2041
/* XXX FIXME up to now, we assume that all chunk are one after one */
2042
static int AVI_StreamBytesSet( demux_t    *p_demux,
2043
                               avi_track_t *p_stream,
2044
                               uint64_t  i_byte )
2045
0
{
2046
0
    if( ( p_stream->idx.i_size > 0 )
2047
0
        &&( i_byte < p_stream->idx.p_entry[p_stream->idx.i_size - 1].i_lengthtotal +
2048
0
                p_stream->idx.p_entry[p_stream->idx.i_size - 1].i_length ) )
2049
0
    {
2050
        /* index is valid to find the ck */
2051
        /* uses dichototmie to be fast enough */
2052
0
        int i_idxposc = __MIN( p_stream->i_idxposc, p_stream->idx.i_size - 1 );
2053
0
        int i_idxmax  = p_stream->idx.i_size;
2054
0
        int i_idxmin  = 0;
2055
0
        for( ;; )
2056
0
        {
2057
0
            if( p_stream->idx.p_entry[i_idxposc].i_lengthtotal > i_byte )
2058
0
            {
2059
0
                i_idxmax  = i_idxposc ;
2060
0
                i_idxposc = ( i_idxmin + i_idxposc ) / 2 ;
2061
0
            }
2062
0
            else
2063
0
            {
2064
0
                if( p_stream->idx.p_entry[i_idxposc].i_lengthtotal +
2065
0
                        p_stream->idx.p_entry[i_idxposc].i_length <= i_byte)
2066
0
                {
2067
0
                    i_idxmin  = i_idxposc ;
2068
0
                    i_idxposc = (i_idxmax + i_idxposc ) / 2 ;
2069
0
                }
2070
0
                else
2071
0
                {
2072
0
                    p_stream->i_idxposc = i_idxposc;
2073
0
                    p_stream->i_idxposb = i_byte -
2074
0
                            p_stream->idx.p_entry[i_idxposc].i_lengthtotal;
2075
0
                    return VLC_SUCCESS;
2076
0
                }
2077
0
            }
2078
0
        }
2079
2080
0
    }
2081
0
    else
2082
0
    {
2083
0
        p_stream->i_idxposc = p_stream->idx.i_size - 1;
2084
0
        p_stream->i_idxposb = 0;
2085
0
        do
2086
0
        {
2087
0
            p_stream->i_idxposc++;
2088
0
            if( AVI_StreamChunkFind( p_demux, p_stream ) )
2089
0
            {
2090
0
                return VLC_EGENERIC;
2091
0
            }
2092
2093
0
        } while( p_stream->idx.p_entry[p_stream->i_idxposc].i_lengthtotal +
2094
0
                    p_stream->idx.p_entry[p_stream->i_idxposc].i_length <= i_byte );
2095
2096
0
        p_stream->i_idxposb = i_byte -
2097
0
                       p_stream->idx.p_entry[p_stream->i_idxposc].i_lengthtotal;
2098
0
        return VLC_SUCCESS;
2099
0
    }
2100
0
}
2101
2102
static int AVI_TrackSeek( demux_t *p_demux,
2103
                           int i_stream,
2104
                           vlc_tick_t i_date )
2105
0
{
2106
0
    demux_sys_t  *p_sys = p_demux->p_sys;
2107
0
    avi_track_t  *tk = p_sys->track[i_stream];
2108
0
    vlc_tick_t i_oldpts;
2109
2110
0
    if( tk->fmt.i_cat == SPU_ES )
2111
0
        return AVI_SeekSubtitleTrack( p_sys, tk );
2112
2113
0
    i_oldpts = AVI_GetPTS( tk );
2114
2115
0
    if( !tk->i_samplesize )
2116
0
    {
2117
0
        if( AVI_StreamChunkSet( p_demux, tk, AVI_PTSToChunk( tk, i_date ) ) )
2118
0
        {
2119
0
            return VLC_EGENERIC;
2120
0
        }
2121
2122
0
        if( tk->fmt.i_cat == AUDIO_ES )
2123
0
        {
2124
0
            if( tk->i_blocksize > 0 )
2125
0
            {
2126
0
                tk->i_blockno = tk->i_idxposc;
2127
0
            }
2128
0
            else
2129
0
            {
2130
0
                tk->i_blockno = 0;
2131
0
                for( unsigned int i = 0; i < tk->i_idxposc; i++ )
2132
0
                    tk->i_blockno += ( tk->idx.p_entry[i].i_length + tk->i_blocksize - 1 ) / tk->i_blocksize;
2133
0
            }
2134
0
        }
2135
2136
0
        msg_Dbg( p_demux,
2137
0
                 "old:%"PRId64" %s new %"PRId64,
2138
0
                 i_oldpts,
2139
0
                 i_oldpts > i_date ? ">" : "<",
2140
0
                 i_date );
2141
2142
0
        if( tk->fmt.i_cat == VIDEO_ES )
2143
0
        {
2144
            /* search key frame */
2145
            //if( i_date < i_oldpts || 1 )
2146
0
            {
2147
0
                while( tk->i_idxposc > 0 &&
2148
0
                   !( tk->idx.p_entry[tk->i_idxposc].i_flags & AVIIF_KEYFRAME ) )
2149
0
                {
2150
0
                    if( AVI_StreamChunkSet( p_demux, tk, tk->i_idxposc - 1 ) )
2151
0
                    {
2152
0
                        return VLC_EGENERIC;
2153
0
                    }
2154
0
                }
2155
0
            }
2156
#if 0
2157
            else
2158
            {
2159
                while( tk->i_idxposc < tk->idx.i_size &&
2160
                        !( tk->idx.p_entry[tk->i_idxposc].i_flags & AVIIF_KEYFRAME ) )
2161
                {
2162
                    if( AVI_StreamChunkSet( p_demux, tk, tk->i_idxposc + 1 ) )
2163
                    {
2164
                        return VLC_EGENERIC;
2165
                    }
2166
                }
2167
            }
2168
#endif
2169
0
        }
2170
0
    }
2171
0
    else
2172
0
    {
2173
0
        if( AVI_StreamBytesSet( p_demux, tk, AVI_PTSToByte( tk, i_date ) ) )
2174
0
        {
2175
0
            return VLC_EGENERIC;
2176
0
        }
2177
0
    }
2178
0
    return VLC_SUCCESS;
2179
0
}
2180
2181
/****************************************************************************
2182
 * Return true if it's a key frame
2183
 ****************************************************************************/
2184
static int AVI_GetKeyFlag( const avi_track_t *tk, const uint8_t *p_byte )
2185
12.2k
{
2186
12.2k
    if( tk->is_qnap )
2187
740
    {
2188
740
        const uint8_t *p = p_byte;
2189
740
        if( IsQNAPCodec(VLC_FOURCC(p[0],p[1],p[2],p[3])) )
2190
4
            return p[4] & 0x01 ? AVIIF_KEYFRAME : 0;
2191
740
    }
2192
2193
12.2k
    switch( tk->fmt.i_codec )
2194
12.2k
    {
2195
342
        case VLC_CODEC_DIV1:
2196
            /* we have:
2197
             *  startcode:      0x00000100   32bits
2198
             *  framenumber     ?             5bits
2199
             *  piture type     0(I),1(P)     2bits
2200
             */
2201
342
            if( GetDWBE( p_byte ) != 0x00000100 )
2202
341
            {
2203
                /* it's not an msmpegv1 stream, strange...*/
2204
341
                return AVIIF_KEYFRAME;
2205
341
            }
2206
1
            return p_byte[4] & 0x06 ? 0 : AVIIF_KEYFRAME;
2207
2208
211
        case VLC_CODEC_DIV2:
2209
428
        case VLC_CODEC_DIV3:
2210
504
        case VLC_CODEC_WMV1:
2211
            /* we have
2212
             *  picture type    0(I),1(P)     2bits
2213
             */
2214
504
            return p_byte[0] & 0xC0 ? 0 : AVIIF_KEYFRAME;
2215
874
        case VLC_CODEC_MP4V:
2216
            /* we should find first occurrence of 0x000001b6 (32bits)
2217
             *  startcode:      0x000001b6   32bits
2218
             *  piture type     0(I),1(P)     2bits
2219
             */
2220
874
            if( GetDWBE( p_byte ) != 0x000001b6 )
2221
872
            {
2222
                /* not true , need to find the first VOP header */
2223
872
                return AVIIF_KEYFRAME;
2224
872
            }
2225
2
            return p_byte[4] & 0xC0 ? 0 : AVIIF_KEYFRAME;
2226
2227
870
        case VLC_CODEC_H264:
2228
870
        {
2229
870
            uint32_t bytes = GetDWBE( p_byte );
2230
870
            enum h264_nal_unit_type_e i_nal_type;
2231
870
            if( bytes == 0x00000001 )
2232
346
                i_nal_type = h264_getNALType( &p_byte[4] );
2233
524
            else if( (bytes & 0xFFFFFF00) == 0x00000100 )
2234
16
                i_nal_type = h264_getNALType( &p_byte[3] );
2235
508
            else
2236
508
                return i_nal_type = 0;
2237
362
            return (i_nal_type == H264_NAL_SLICE_IDR) ? AVIIF_KEYFRAME : 0;
2238
870
        }
2239
2240
329
        case VLC_CODEC_HEVC:
2241
329
        {
2242
329
            uint32_t bytes = GetDWBE( p_byte );
2243
329
            uint8_t i_nal_type;
2244
329
            if( bytes == 0x00000001 )
2245
3
                i_nal_type = hevc_getNALType( &p_byte[4] );
2246
326
            else if( (bytes & 0xFFFFFF00) == 0x00000100 )
2247
7
                i_nal_type = hevc_getNALType( &p_byte[3] );
2248
319
            else
2249
319
                i_nal_type = 0;
2250
329
            return (i_nal_type >= HEVC_NAL_IDR_W_RADL &&
2251
329
                    i_nal_type <= HEVC_NAL_CRA) ? AVIIF_KEYFRAME : 0;
2252
870
        }
2253
2254
9.36k
        default:
2255
            /* I can't do it, so say yes */
2256
9.36k
            return AVIIF_KEYFRAME;
2257
12.2k
    }
2258
12.2k
}
2259
2260
vlc_fourcc_t AVI_FourccGetCodec( unsigned int i_cat, vlc_fourcc_t i_codec )
2261
10.0k
{
2262
10.0k
    switch( i_cat )
2263
10.0k
    {
2264
8.54k
        case AUDIO_ES:
2265
8.54k
            wf_tag_to_fourcc( i_codec, &i_codec, NULL );
2266
8.54k
            return i_codec;
2267
1.53k
        case VIDEO_ES:
2268
1.53k
            return vlc_fourcc_GetCodec( i_cat, i_codec );
2269
0
        default:
2270
0
            return VLC_CODEC_UNKNOWN;
2271
10.0k
    }
2272
10.0k
}
2273
2274
/****************************************************************************
2275
 *
2276
 ****************************************************************************/
2277
static void AVI_ParseStreamHeader( vlc_fourcc_t i_id,
2278
                                   unsigned int *pi_number,
2279
                                   enum es_format_category_e *pi_type )
2280
2.11M
{
2281
2.11M
    int c1, c2;
2282
2283
2.11M
    c1 = ((uint8_t *)&i_id)[0];
2284
2.11M
    c2 = ((uint8_t *)&i_id)[1];
2285
2286
2.11M
    if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
2287
1.56M
    {
2288
1.56M
        *pi_number =  100; /* > max stream number */
2289
1.56M
        *pi_type = UNKNOWN_ES;
2290
1.56M
    }
2291
548k
    else
2292
548k
    {
2293
548k
        *pi_number = (c1 - '0') * 10 + (c2 - '0' );
2294
548k
        switch( VLC_TWOCC( ((uint8_t *)&i_id)[2], ((uint8_t *)&i_id)[3] ) )
2295
548k
        {
2296
22.3k
            case AVITWOCC_wb:
2297
22.3k
                *pi_type = AUDIO_ES;
2298
22.3k
                break;
2299
2.97k
            case AVITWOCC_dc:
2300
3.05k
            case AVITWOCC_db:
2301
3.06k
            case AVITWOCC_AC:
2302
3.06k
                *pi_type = VIDEO_ES;
2303
3.06k
                break;
2304
37
            case AVITWOCC_tx:
2305
115
            case AVITWOCC_sb:
2306
115
                *pi_type = SPU_ES;
2307
115
                break;
2308
31
            case AVITWOCC_pc:
2309
31
                *pi_type = IGNORE_ES;
2310
31
                break;
2311
522k
            default:
2312
522k
                *pi_type = UNKNOWN_ES;
2313
522k
                break;
2314
548k
        }
2315
548k
    }
2316
2.11M
}
2317
2318
/****************************************************************************
2319
 *
2320
 ****************************************************************************/
2321
static int AVI_PacketGetHeader( demux_t *p_demux, avi_packet_t *p_pk )
2322
20.3M
{
2323
20.3M
    const uint8_t *p_peek;
2324
2325
20.3M
    if( vlc_stream_Peek( p_demux->s, &p_peek, 16 ) < 16 )
2326
18.3M
    {
2327
18.3M
        return VLC_EGENERIC;
2328
18.3M
    }
2329
2.03M
    p_pk->i_fourcc  = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] );
2330
2.03M
    p_pk->i_size    = GetDWLE( p_peek + 4 );
2331
2.03M
    p_pk->i_pos     = vlc_stream_Tell( p_demux->s );
2332
2.03M
    if( p_pk->i_fourcc == AVIFOURCC_LIST || p_pk->i_fourcc == AVIFOURCC_RIFF )
2333
518k
    {
2334
518k
        p_pk->i_type = VLC_FOURCC( p_peek[8],  p_peek[9],
2335
518k
                                   p_peek[10], p_peek[11] );
2336
518k
    }
2337
1.51M
    else
2338
1.51M
    {
2339
1.51M
        p_pk->i_type = 0;
2340
1.51M
    }
2341
2342
2.03M
    memcpy( p_pk->i_peek, p_peek + 8, 8 );
2343
2344
2.03M
    AVI_ParseStreamHeader( p_pk->i_fourcc, &p_pk->i_stream, &p_pk->i_cat );
2345
2.03M
    return VLC_SUCCESS;
2346
20.3M
}
2347
2348
static int AVI_PacketNext( demux_t *p_demux )
2349
19.5M
{
2350
19.5M
    avi_packet_t    avi_ck;
2351
19.5M
    uint32_t        i_skip = 0;
2352
2353
19.5M
    if( AVI_PacketGetHeader( p_demux, &avi_ck ) )
2354
18.2M
    {
2355
18.2M
        return VLC_EGENERIC;
2356
18.2M
    }
2357
2358
1.33M
    if( avi_ck.i_fourcc == AVIFOURCC_LIST &&
2359
1.33M
        ( avi_ck.i_type == AVIFOURCC_rec || avi_ck.i_type == AVIFOURCC_movi ) )
2360
209k
    {
2361
209k
        i_skip = 12;
2362
209k
    }
2363
1.12M
    else if( avi_ck.i_fourcc == AVIFOURCC_RIFF &&
2364
1.12M
             avi_ck.i_type == AVIFOURCC_AVIX )
2365
10
    {
2366
10
        i_skip = 24;
2367
10
    }
2368
1.12M
    else
2369
1.12M
    {
2370
1.12M
        if( avi_ck.i_size > UINT32_MAX - 9 )
2371
2.15k
            return VLC_EGENERIC;
2372
1.12M
        i_skip = __EVEN( avi_ck.i_size ) + 8;
2373
1.12M
    }
2374
2375
#if SSIZE_MAX < UINT32_MAX // otherwise i_skip can't be bigger than SSIZE_MAX
2376
    if (i_skip > SSIZE_MAX)
2377
        return VLC_EGENERIC;
2378
#endif
2379
2380
1.33M
    if( vlc_stream_Read( p_demux->s, NULL, i_skip ) != i_skip )
2381
823k
    {
2382
823k
        return VLC_EGENERIC;
2383
823k
    }
2384
511k
    return VLC_SUCCESS;
2385
1.33M
}
2386
2387
static int AVI_PacketSearch( demux_t *p_demux )
2388
0
{
2389
0
    demux_sys_t     *p_sys = p_demux->p_sys;
2390
0
    avi_packet_t    avi_pk;
2391
0
    unsigned short  i_count = 0;
2392
2393
0
    for( ;; )
2394
0
    {
2395
0
        if( vlc_stream_Read( p_demux->s, NULL, 1 ) != 1 )
2396
0
        {
2397
0
            return VLC_EGENERIC;
2398
0
        }
2399
0
        AVI_PacketGetHeader( p_demux, &avi_pk );
2400
0
        if( avi_pk.i_stream < p_sys->i_track &&
2401
0
            ( avi_pk.i_cat == AUDIO_ES || avi_pk.i_cat == VIDEO_ES ) )
2402
0
        {
2403
0
            return VLC_SUCCESS;
2404
0
        }
2405
0
        switch( avi_pk.i_fourcc )
2406
0
        {
2407
0
            case AVIFOURCC_JUNK:
2408
0
            case AVIFOURCC_LIST:
2409
0
            case AVIFOURCC_RIFF:
2410
0
            case AVIFOURCC_idx1:
2411
0
                return VLC_SUCCESS;
2412
0
        }
2413
2414
0
        if( !++i_count )
2415
0
            msg_Warn( p_demux, "trying to resync..." );
2416
0
    }
2417
0
}
2418
2419
/****************************************************************************
2420
 * Index stuff.
2421
 ****************************************************************************/
2422
static void avi_index_Init( avi_index_t *p_index )
2423
34.5k
{
2424
34.5k
    p_index->i_size  = 0;
2425
34.5k
    p_index->i_max   = 0;
2426
34.5k
    p_index->p_entry = NULL;
2427
34.5k
}
2428
static void avi_index_Clean( avi_index_t *p_index )
2429
34.5k
{
2430
34.5k
    free( p_index->p_entry );
2431
34.5k
}
2432
153k
#define MAX_INDEX_ENTRIES __MIN(SIZE_MAX/sizeof(avi_entry_t), UINT32_MAX)
2433
7.93k
#define INDEX_EXTENT 16384
2434
static int64_t avi_index_Append( avi_index_t *p_index, uint64_t *pi_last_pos,
2435
                                 avi_entry_t *p_entry )
2436
149k
{
2437
    /* Update last chunk position */
2438
149k
    if( *pi_last_pos < p_entry->i_pos )
2439
14.1k
         *pi_last_pos = p_entry->i_pos;
2440
2441
149k
    if( p_index->i_size == MAX_INDEX_ENTRIES )
2442
0
        return -1;
2443
2444
    /* add the entry */
2445
149k
    if( p_index->i_size >= p_index->i_max )
2446
3.96k
    {
2447
3.96k
        if( MAX_INDEX_ENTRIES - INDEX_EXTENT > p_index->i_max )
2448
3.96k
            p_index->i_max += INDEX_EXTENT;
2449
0
        else
2450
0
            p_index->i_max = MAX_INDEX_ENTRIES;
2451
3.96k
        p_index->p_entry = realloc_or_free( p_index->p_entry,
2452
3.96k
                                            p_index->i_max * sizeof(avi_entry_t) );
2453
3.96k
        if( !p_index->p_entry )
2454
0
        {
2455
0
            avi_index_Init( p_index );
2456
0
            return -1;
2457
0
        }
2458
3.96k
    }
2459
    /* calculate cumulate length */
2460
149k
    if( p_index->i_size > 0 )
2461
145k
    {
2462
145k
        p_entry->i_lengthtotal =
2463
145k
            p_index->p_entry[p_index->i_size - 1].i_length +
2464
145k
                p_index->p_entry[p_index->i_size - 1].i_lengthtotal;
2465
145k
    }
2466
3.96k
    else
2467
3.96k
    {
2468
3.96k
        p_entry->i_lengthtotal = 0;
2469
3.96k
    }
2470
2471
149k
    p_index->p_entry[p_index->i_size++] = *p_entry;
2472
149k
    return p_index->i_size - 1;
2473
149k
}
2474
2475
static int AVI_IndexFind_idx1( demux_t *p_demux,
2476
                               avi_chunk_idx1_t **pp_idx1,
2477
                               uint64_t *pi_offset )
2478
11.4k
{
2479
11.4k
    demux_sys_t *p_sys = p_demux->p_sys;
2480
2481
11.4k
    avi_chunk_list_t *p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0, true);
2482
11.4k
    avi_chunk_idx1_t *p_idx1 = AVI_ChunkFind( p_riff, AVIFOURCC_idx1, 0, false);
2483
2484
11.4k
    if( !p_idx1 )
2485
10.3k
    {
2486
10.3k
        msg_Warn( p_demux, "cannot find idx1 chunk, no index defined" );
2487
10.3k
        return VLC_EGENERIC;
2488
10.3k
    }
2489
1.07k
    *pp_idx1 = p_idx1;
2490
2491
    /* The offset in the index should be from the start of the movi content,
2492
     * but some broken files use offset from the start of the file. Just
2493
     * checking the offset of the first packet is not enough as some files
2494
     * has unused chunk at the beginning of the movi content.
2495
     */
2496
1.07k
    avi_chunk_list_t *p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0, true );
2497
1.07k
    if( !p_movi )
2498
5
        return VLC_EGENERIC;
2499
1.06k
    uint64_t i_first_pos = UINT64_MAX;
2500
49.6k
    for( unsigned i = 0; i < __MIN( p_idx1->i_entry_count, 100 ); i++ )
2501
48.5k
    {
2502
48.5k
        if ( p_idx1->entry[i].i_length > 0 )
2503
38.2k
            i_first_pos = __MIN( i_first_pos, p_idx1->entry[i].i_pos );
2504
48.5k
    }
2505
2506
1.06k
    const uint64_t i_movi_content = p_movi->i_chunk_pos + 8;
2507
1.06k
    if( i_first_pos < i_movi_content )
2508
607
    {
2509
607
        *pi_offset = i_movi_content;
2510
607
    }
2511
460
    else if( p_sys->b_seekable && i_first_pos < UINT64_MAX )
2512
421
    {
2513
421
        const uint8_t *p_peek;
2514
421
        if( !vlc_stream_Seek( p_demux->s, i_movi_content + i_first_pos ) &&
2515
421
            vlc_stream_Peek( p_demux->s, &p_peek, 4 ) >= 4 &&
2516
421
            ( !isdigit( p_peek[0] ) || !isdigit( p_peek[1] ) ||
2517
64
              !isalpha( p_peek[2] ) || !isalpha( p_peek[3] ) ) )
2518
61
            *pi_offset = 0;
2519
360
        else
2520
360
            *pi_offset = i_movi_content;
2521
2522
421
        if( p_idx1->i_entry_count )
2523
421
        {
2524
            /* Invalidate offset if index refers past the data section to avoid false
2525
               positives when the offset equals sample size */
2526
421
            size_t i_dataend = *pi_offset + p_idx1->entry[p_idx1->i_entry_count - 1].i_pos +
2527
421
                                            p_idx1->entry[p_idx1->i_entry_count - 1].i_length;
2528
421
            if( i_dataend > p_movi->i_chunk_pos + p_movi->i_chunk_size )
2529
350
                *pi_offset = 0;
2530
421
        }
2531
421
    }
2532
39
    else
2533
39
    {
2534
39
        *pi_offset = 0;
2535
39
    }
2536
2537
1.06k
    return VLC_SUCCESS;
2538
1.07k
}
2539
2540
static int AVI_IndexLoad_idx1( demux_t *p_demux,
2541
                               avi_index_t p_index[], uint64_t *pi_last_offset )
2542
11.2k
{
2543
11.2k
    demux_sys_t *p_sys = p_demux->p_sys;
2544
2545
11.2k
    avi_chunk_idx1_t *p_idx1;
2546
11.2k
    uint64_t         i_offset;
2547
11.2k
    if( AVI_IndexFind_idx1( p_demux, &p_idx1, &i_offset ) )
2548
10.3k
        return VLC_EGENERIC;
2549
2550
919
    p_sys->b_indexloaded = true;
2551
2552
67.4k
    for( unsigned i_index = 0; i_index < p_idx1->i_entry_count; i_index++ )
2553
66.5k
    {
2554
66.5k
        enum es_format_category_e i_cat;
2555
66.5k
        unsigned i_stream;
2556
2557
66.5k
        AVI_ParseStreamHeader( p_idx1->entry[i_index].i_fourcc,
2558
66.5k
                               &i_stream,
2559
66.5k
                               &i_cat );
2560
66.5k
        if( i_stream < p_sys->i_track &&
2561
66.5k
            (i_cat == p_sys->track[i_stream]->fmt.i_cat || i_cat == UNKNOWN_ES ) )
2562
3.42k
        {
2563
3.42k
            avi_entry_t index;
2564
3.42k
            index.i_flags  = p_idx1->entry[i_index].i_flags&(~AVIIF_FIXKEYFRAME);
2565
3.42k
            index.i_pos    = p_idx1->entry[i_index].i_pos + i_offset;
2566
3.42k
            index.i_length = p_idx1->entry[i_index].i_length;
2567
3.42k
            index.i_lengthtotal = index.i_length;
2568
2569
3.42k
            avi_index_Append( &p_index[i_stream], pi_last_offset, &index );
2570
3.42k
        }
2571
66.5k
    }
2572
2573
#ifdef AVI_DEBUG
2574
    for( unsigned i_index = 0; i_index< p_idx1->i_entry_count && i_index < p_sys->i_track; i_index++ )
2575
    {
2576
        for( unsigned i = 0; i < p_index[i_index].i_size; i++ )
2577
        {
2578
            vlc_tick_t i_length;
2579
            if( p_sys->track[i_index]->i_samplesize )
2580
            {
2581
                i_length = AVI_GetDPTS( p_sys->track[i_index],
2582
                                        p_index[i_index].p_entry[i].i_lengthtotal );
2583
            }
2584
            else
2585
            {
2586
                i_length = AVI_GetDPTS( p_sys->track[i_index], i );
2587
            }
2588
            msg_Dbg( p_demux, "index stream %d @%ld time %ld", i_index,
2589
                     p_index[i_index].p_entry[i].i_pos, i_length );
2590
        }
2591
    }
2592
#endif
2593
919
    return VLC_SUCCESS;
2594
11.2k
}
2595
2596
static void __Parse_indx( demux_t *p_demux, avi_index_t *p_index, uint64_t *pi_max_offset,
2597
                          avi_chunk_indx_t *p_indx )
2598
1.64k
{
2599
1.64k
    demux_sys_t *p_sys = p_demux->p_sys;
2600
1.64k
    avi_entry_t index;
2601
2602
1.64k
    p_sys->b_indexloaded = true;
2603
2604
1.64k
    msg_Dbg( p_demux, "loading subindex(0x%x) %d entries", p_indx->i_indextype, p_indx->i_entriesinuse );
2605
1.64k
    if( p_indx->i_indexsubtype == 0 )
2606
1.04k
    {
2607
119k
        for( unsigned i = 0; i < p_indx->i_entriesinuse; i++ )
2608
118k
        {
2609
118k
            index.i_flags  = p_indx->idx.std[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
2610
118k
            index.i_pos    = p_indx->i_baseoffset + p_indx->idx.std[i].i_offset - 8;
2611
118k
            index.i_length = p_indx->idx.std[i].i_size&0x7fffffff;
2612
118k
            index.i_lengthtotal = index.i_length;
2613
2614
118k
            avi_index_Append( p_index, pi_max_offset, &index );
2615
118k
        }
2616
1.04k
    }
2617
599
    else if( p_indx->i_indexsubtype == AVI_INDEX_2FIELD )
2618
320
    {
2619
15.3k
        for( unsigned i = 0; i < p_indx->i_entriesinuse; i++ )
2620
15.0k
        {
2621
15.0k
            index.i_flags  = p_indx->idx.field[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
2622
15.0k
            index.i_pos    = p_indx->i_baseoffset + p_indx->idx.field[i].i_offset - 8;
2623
15.0k
            index.i_length = p_indx->idx.field[i].i_size;
2624
15.0k
            index.i_lengthtotal = index.i_length;
2625
2626
15.0k
            avi_index_Append( p_index, pi_max_offset, &index );
2627
15.0k
        }
2628
320
    }
2629
279
    else
2630
279
    {
2631
279
        msg_Warn( p_demux, "unknown subtype index(0x%x)", p_indx->i_indexsubtype );
2632
279
    }
2633
1.64k
}
2634
2635
static void AVI_IndexLoad_indx( demux_t *p_demux,
2636
                                avi_index_t p_index[], uint64_t *pi_last_offset )
2637
11.2k
{
2638
11.2k
    demux_sys_t         *p_sys = p_demux->p_sys;
2639
2640
11.2k
    avi_chunk_list_t    *p_riff;
2641
11.2k
    avi_chunk_list_t    *p_hdrl;
2642
2643
11.2k
    p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0, true);
2644
11.2k
    p_hdrl = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0, true );
2645
2646
28.5k
    for( unsigned i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
2647
17.2k
    {
2648
17.2k
        avi_chunk_list_t    *p_strl;
2649
17.2k
        avi_chunk_indx_t    *p_indx;
2650
2651
17.2k
        p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i_stream, true );
2652
17.2k
        p_indx = AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0, false );
2653
2654
17.2k
        if( !p_indx )
2655
16.3k
        {
2656
16.3k
            if( p_sys->b_odml )
2657
16.3k
                msg_Warn( p_demux, "cannot find indx (misdetect/broken OpenDML "
2658
16.3k
                                   "file?)" );
2659
16.3k
            continue;
2660
16.3k
        }
2661
2662
908
        if( p_indx->i_indextype == AVI_INDEX_OF_CHUNKS )
2663
246
        {
2664
246
            __Parse_indx( p_demux, &p_index[i_stream], pi_last_offset, p_indx );
2665
246
        }
2666
662
        else if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES )
2667
653
        {
2668
653
            if ( !p_sys->b_seekable )
2669
0
                return;
2670
653
            avi_chunk_t    ck_sub;
2671
23.6k
            for( unsigned i = 0; i < p_indx->i_entriesinuse; i++ )
2672
23.6k
            {
2673
23.6k
                if( vlc_stream_Seek( p_demux->s,
2674
23.6k
                                     p_indx->idx.super[i].i_offset ) ||
2675
23.6k
                    AVI_ChunkRead( p_demux->s, &ck_sub, NULL  ) )
2676
613
                {
2677
613
                    break;
2678
613
                }
2679
22.9k
                if( ck_sub.common.i_chunk_fourcc == AVIFOURCC_indx &&
2680
22.9k
                     ck_sub.indx.i_indextype == AVI_INDEX_OF_CHUNKS )
2681
1.39k
                    __Parse_indx( p_demux, &p_index[i_stream], pi_last_offset, &ck_sub.indx );
2682
22.9k
                AVI_ChunkClean( p_demux->s, &ck_sub );
2683
22.9k
            }
2684
653
        }
2685
9
        else
2686
9
        {
2687
9
            msg_Warn( p_demux, "unknown type index(0x%x)", p_indx->i_indextype );
2688
9
        }
2689
908
    }
2690
11.2k
}
2691
2692
static void AVI_IndexLoad( demux_t *p_demux )
2693
11.2k
{
2694
11.2k
    demux_sys_t *p_sys = p_demux->p_sys;
2695
2696
    /* Load indexes */
2697
11.2k
    assert( p_sys->i_track <= 100 );
2698
11.2k
    avi_index_t p_idx_indx[p_sys->i_track];
2699
11.2k
    avi_index_t p_idx_idx1[p_sys->i_track];
2700
28.5k
    for( unsigned i = 0; i < p_sys->i_track; i++ )
2701
17.2k
    {
2702
17.2k
        avi_index_Init( &p_idx_indx[i] );
2703
17.2k
        avi_index_Init( &p_idx_idx1[i] );
2704
17.2k
    }
2705
11.2k
    uint64_t i_indx_last_pos = p_sys->i_movi_lastchunk_pos;
2706
11.2k
    uint64_t i_idx1_last_pos = p_sys->i_movi_lastchunk_pos;
2707
2708
11.2k
    AVI_IndexLoad_indx( p_demux, p_idx_indx, &i_indx_last_pos );
2709
11.2k
    if( !p_sys->b_odml )
2710
11.2k
        AVI_IndexLoad_idx1( p_demux, p_idx_idx1, &i_idx1_last_pos );
2711
2712
    /* Select the longest index */
2713
28.5k
    for( unsigned i = 0; i < p_sys->i_track; i++ )
2714
17.2k
    {
2715
17.2k
        if( p_idx_indx[i].i_size > p_idx_idx1[i].i_size )
2716
273
        {
2717
273
            msg_Dbg( p_demux, "selected ODML index for stream[%u]", i );
2718
273
            free(p_sys->track[i]->idx.p_entry);
2719
273
            p_sys->track[i]->idx = p_idx_indx[i];
2720
273
            avi_index_Clean( &p_idx_idx1[i] );
2721
273
        }
2722
16.9k
        else
2723
16.9k
        {
2724
16.9k
            msg_Dbg( p_demux, "selected standard index for stream[%u]", i );
2725
16.9k
            free(p_sys->track[i]->idx.p_entry);
2726
16.9k
            p_sys->track[i]->idx = p_idx_idx1[i];
2727
16.9k
            avi_index_Clean( &p_idx_indx[i] );
2728
16.9k
        }
2729
17.2k
    }
2730
11.2k
    p_sys->i_movi_lastchunk_pos = __MAX( i_indx_last_pos, i_idx1_last_pos );
2731
2732
28.5k
    for( unsigned i = 0; i < p_sys->i_track; i++ )
2733
17.2k
    {
2734
17.2k
        avi_index_t *p_index = &p_sys->track[i]->idx;
2735
2736
        /* Fix key flag */
2737
17.2k
        bool b_key = false;
2738
18.8k
        for( unsigned j = 0; !b_key && j < p_index->i_size; j++ )
2739
1.55k
            b_key = p_index->p_entry[j].i_flags & AVIIF_KEYFRAME;
2740
17.2k
        if( !b_key )
2741
16.5k
        {
2742
16.5k
            msg_Warn( p_demux, "no key frame set for track %u", i );
2743
16.9k
            for( unsigned j = 0; j < p_index->i_size; j++ )
2744
416
                p_index->p_entry[j].i_flags |= AVIIF_KEYFRAME;
2745
16.5k
        }
2746
2747
        /* */
2748
17.2k
        msg_Dbg( p_demux, "stream[%d] created %d index entries",
2749
17.2k
                 i, p_index->i_size );
2750
17.2k
    }
2751
11.2k
}
2752
2753
static void AVI_IndexCreate( demux_t *p_demux )
2754
0
{
2755
0
    demux_sys_t *p_sys = p_demux->p_sys;
2756
2757
0
    avi_chunk_list_t *p_riff;
2758
0
    avi_chunk_list_t *p_movi;
2759
2760
0
    unsigned int i_stream;
2761
0
    uint32_t i_movi_end;
2762
2763
0
    vlc_tick_t i_dialog_update;
2764
0
    vlc_dialog_id *p_dialog_id = NULL;
2765
2766
0
    p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0, true );
2767
0
    p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0, true );
2768
2769
0
    if( !p_movi )
2770
0
    {
2771
0
        msg_Err( p_demux, "cannot find p_movi" );
2772
0
        return;
2773
0
    }
2774
2775
0
    for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
2776
0
        avi_index_Init( &p_sys->track[i_stream]->idx );
2777
2778
0
    i_movi_end = __MIN( (uint32_t)(p_movi->i_chunk_pos + p_movi->i_chunk_size),
2779
0
                        stream_Size( p_demux->s ) );
2780
2781
0
    vlc_stream_Seek( p_demux->s, p_movi->i_chunk_pos + 12 );
2782
0
    msg_Warn( p_demux, "creating index from LIST-movi, will take time !" );
2783
2784
2785
    /* Only show dialog if AVI is > 10MB */
2786
0
    i_dialog_update = vlc_tick_now();
2787
0
    if( stream_Size( p_demux->s ) > 10000000 )
2788
0
    {
2789
0
        p_dialog_id =
2790
0
            vlc_dialog_display_progress( p_demux, false, 0.0, _("Cancel"),
2791
0
                                         _("Broken or missing AVI Index"),
2792
0
                                         _("Fixing AVI Index...") );
2793
0
    }
2794
2795
0
    for( ;; )
2796
0
    {
2797
0
        avi_packet_t pk;
2798
2799
        /* Don't update/check dialog too often */
2800
0
        if( p_dialog_id != NULL && vlc_tick_now() - i_dialog_update > VLC_TICK_FROM_MS(100) )
2801
0
        {
2802
0
            if( vlc_dialog_is_cancelled( p_demux, p_dialog_id ) )
2803
0
                break;
2804
2805
0
            double f_current = vlc_stream_Tell( p_demux->s );
2806
0
            double f_size    = stream_Size( p_demux->s );
2807
0
            double f_pos     = f_current / f_size;
2808
0
            vlc_dialog_update_progress( p_demux, p_dialog_id, f_pos );
2809
2810
0
            i_dialog_update = vlc_tick_now();
2811
0
        }
2812
2813
0
        if( AVI_PacketGetHeader( p_demux, &pk ) )
2814
0
            break;
2815
2816
0
        if( pk.i_stream < p_sys->i_track &&
2817
0
            pk.i_cat == p_sys->track[pk.i_stream]->fmt.i_cat )
2818
0
        {
2819
0
            avi_track_t *tk = p_sys->track[pk.i_stream];
2820
2821
0
            avi_entry_t index;
2822
0
            index.i_flags   = AVI_GetKeyFlag(tk, pk.i_peek);
2823
0
            index.i_pos     = pk.i_pos;
2824
0
            index.i_length  = pk.i_size;
2825
0
            index.i_lengthtotal = pk.i_size;
2826
0
            avi_index_Append( &tk->idx, &p_sys->i_movi_lastchunk_pos, &index );
2827
0
        }
2828
0
        else
2829
0
        {
2830
0
            switch( pk.i_fourcc )
2831
0
            {
2832
0
            case AVIFOURCC_idx1:
2833
0
                if( p_sys->b_odml )
2834
0
                {
2835
0
                    avi_chunk_list_t *p_sysx;
2836
0
                    p_sysx = AVI_ChunkFind( &p_sys->ck_root,
2837
0
                                            AVIFOURCC_RIFF, 1, true );
2838
2839
0
                    msg_Dbg( p_demux, "looking for new RIFF chunk" );
2840
0
                    if( !p_sysx || vlc_stream_Seek( p_demux->s,
2841
0
                                         p_sysx->i_chunk_pos + 24 ) )
2842
0
                        goto print_stat;
2843
0
                    break;
2844
0
                }
2845
0
                goto print_stat;
2846
2847
0
            case AVIFOURCC_RIFF:
2848
0
                    msg_Dbg( p_demux, "new RIFF chunk found" );
2849
0
                    break;
2850
2851
0
            case AVIFOURCC_rec:
2852
0
            case AVIFOURCC_JUNK:
2853
0
                break;
2854
2855
0
            default:
2856
0
                msg_Warn( p_demux, "need resync, probably broken avi" );
2857
0
                if( AVI_PacketSearch( p_demux ) )
2858
0
                {
2859
0
                    msg_Warn( p_demux, "lost sync, abord index creation" );
2860
0
                    goto print_stat;
2861
0
                }
2862
0
            }
2863
0
        }
2864
2865
0
        if( ( !p_sys->b_odml && pk.i_pos + pk.i_size >= i_movi_end ) ||
2866
0
            AVI_PacketNext( p_demux ) )
2867
0
        {
2868
0
            break;
2869
0
        }
2870
0
    }
2871
2872
0
print_stat:
2873
0
    if( p_dialog_id != NULL )
2874
0
        vlc_dialog_release( p_demux, p_dialog_id );
2875
2876
0
    for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
2877
0
    {
2878
0
        msg_Dbg( p_demux, "stream[%d] creating %d index entries",
2879
0
                i_stream, p_sys->track[i_stream]->idx.i_size );
2880
0
    }
2881
0
}
2882
2883
/* */
2884
static void AVI_MetaLoad( demux_t *p_demux,
2885
                          avi_chunk_list_t *p_riff, avi_chunk_avih_t *p_avih )
2886
11.5k
{
2887
11.5k
    demux_sys_t *p_sys = p_demux->p_sys;
2888
2889
11.5k
    vlc_meta_t *p_meta = p_sys->meta = vlc_meta_New();
2890
11.5k
    if( !p_meta )
2891
0
        return;
2892
2893
11.5k
    char buffer[200];
2894
11.5k
    snprintf( buffer, sizeof(buffer), "%s%s%s%s",
2895
11.5k
              p_avih->i_flags&AVIF_HASINDEX      ? " HAS_INDEX"      : "",
2896
11.5k
              p_avih->i_flags&AVIF_MUSTUSEINDEX  ? " MUST_USE_INDEX" : "",
2897
11.5k
              p_avih->i_flags&AVIF_ISINTERLEAVED ? " IS_INTERLEAVED" : "",
2898
11.5k
              p_avih->i_flags&AVIF_TRUSTCKTYPE   ? " TRUST_CKTYPE"   : "" );
2899
11.5k
    vlc_meta_SetSetting( p_meta, buffer );
2900
2901
11.5k
    avi_chunk_list_t *p_info = AVI_ChunkFind( p_riff, AVIFOURCC_INFO, 0, true );
2902
11.5k
    if( !p_info )
2903
10.2k
        return;
2904
2905
1.28k
    static const struct {
2906
1.28k
        vlc_fourcc_t i_id;
2907
1.28k
        int          i_type;
2908
1.28k
    } p_dsc[] = {
2909
1.28k
        { AVIFOURCC_IART, vlc_meta_Artist },
2910
1.28k
        { AVIFOURCC_ICMT, vlc_meta_Description },
2911
1.28k
        { AVIFOURCC_ICOP, vlc_meta_Copyright },
2912
1.28k
        { AVIFOURCC_IGNR, vlc_meta_Genre },
2913
1.28k
        { AVIFOURCC_INAM, vlc_meta_Title },
2914
1.28k
        { AVIFOURCC_ICRD, vlc_meta_Date },
2915
1.28k
        { AVIFOURCC_ILNG, vlc_meta_Language },
2916
1.28k
        { AVIFOURCC_IRTD, vlc_meta_Rating },
2917
1.28k
        { AVIFOURCC_IWEB, vlc_meta_URL },
2918
1.28k
        { AVIFOURCC_IPRT, vlc_meta_TrackNumber },
2919
1.28k
        { AVIFOURCC_IFRM, vlc_meta_TrackTotal },
2920
1.28k
        { 0, -1 }
2921
1.28k
    };
2922
15.4k
    for( int i = 0; p_dsc[i].i_id != 0; i++ )
2923
14.1k
    {
2924
14.1k
        avi_chunk_STRING_t *p_strz = AVI_ChunkFind( p_info, p_dsc[i].i_id, 0, false );
2925
14.1k
        if( !p_strz || !p_strz->p_str )
2926
14.1k
            continue;
2927
21
        char *psz_value = FromACP( p_strz->p_str );
2928
21
        if( !psz_value )
2929
1
            continue;
2930
2931
20
        if( *psz_value )
2932
19
            vlc_meta_Set( p_meta, p_dsc[i].i_type, psz_value );
2933
20
        free( psz_value );
2934
20
    }
2935
2936
1.28k
    static const vlc_fourcc_t p_extra[] = {
2937
1.28k
        AVIFOURCC_IARL, AVIFOURCC_ICMS, AVIFOURCC_ICRP, AVIFOURCC_IDIM, AVIFOURCC_IDPI,
2938
1.28k
        AVIFOURCC_IENG, AVIFOURCC_IKEY, AVIFOURCC_ILGT, AVIFOURCC_IMED, AVIFOURCC_IPLT,
2939
1.28k
        AVIFOURCC_IPRD, AVIFOURCC_ISBJ, AVIFOURCC_ISFT, AVIFOURCC_ISHP, AVIFOURCC_ISRC,
2940
1.28k
        AVIFOURCC_ISRF, AVIFOURCC_ITCH, AVIFOURCC_ISMP, AVIFOURCC_IDIT, AVIFOURCC_ISGN,
2941
1.28k
        AVIFOURCC_IWRI, AVIFOURCC_IPRO, AVIFOURCC_ICNM, AVIFOURCC_IPDS, AVIFOURCC_IEDT,
2942
1.28k
        AVIFOURCC_ICDS, AVIFOURCC_IMUS, AVIFOURCC_ISTD, AVIFOURCC_IDST, AVIFOURCC_ICNT,
2943
1.28k
        AVIFOURCC_ISTR, 0,
2944
1.28k
    };
2945
2946
41.2k
    for( int i = 0; p_extra[i] != 0; i++ )
2947
39.9k
    {
2948
39.9k
        avi_chunk_STRING_t *p_strz = AVI_ChunkFind( p_info, p_extra[i], 0, false );
2949
39.9k
        if( !p_strz || !p_strz->p_str )
2950
38.9k
            continue;
2951
1.02k
        char *psz_value = FromACP( p_strz->p_str );
2952
1.02k
        if( !psz_value )
2953
25
            continue;
2954
2955
1.00k
        if( *psz_value )
2956
995
            vlc_meta_SetExtra( p_meta, p_strz->p_type, psz_value );
2957
1.00k
        free( psz_value );
2958
1.00k
    }
2959
1.28k
}
2960
2961
static void AVI_DvHandleAudio( demux_t *p_demux, avi_track_t *tk, block_t *p_frame )
2962
198
{
2963
198
    size_t i_offset = 80 * 6 + 80 * 16 * 3 + 3;
2964
198
    if( p_frame->i_buffer < i_offset + 5 )
2965
85
        return;
2966
2967
113
    if( p_frame->p_buffer[i_offset] != 0x50 )
2968
18
        return;
2969
2970
95
    es_format_t fmt;
2971
95
    dv_get_audio_format( &fmt, &p_frame->p_buffer[i_offset + 1] );
2972
2973
95
    if( tk->p_es_dv_audio && tk->i_dv_audio_rate != (int)fmt.audio.i_rate )
2974
0
    {
2975
0
        es_out_Del( p_demux->out, tk->p_es_dv_audio );
2976
0
        tk->p_es_dv_audio = NULL;
2977
0
    }
2978
2979
95
    if( !tk->p_es_dv_audio )
2980
90
    {
2981
90
        tk->p_es_dv_audio = es_out_Add( p_demux->out, &fmt );
2982
90
        tk->i_dv_audio_rate = fmt.audio.i_rate;
2983
90
    }
2984
2985
95
    es_format_Clean( &fmt );
2986
2987
95
    block_t *p_frame_audio = dv_extract_audio( p_frame );
2988
95
    if( p_frame_audio )
2989
78
    {
2990
78
        if( tk->p_es_dv_audio )
2991
78
            es_out_Send( p_demux->out, tk->p_es_dv_audio, p_frame_audio );
2992
0
        else
2993
0
            block_Release( p_frame_audio );
2994
78
    }
2995
95
}
2996
2997
/*****************************************************************************
2998
 * Subtitles
2999
 *****************************************************************************/
3000
/*
3001
    Subtitles only exists in a hackish way as AVI is samples rate based and
3002
    does not provide any way for variable rate or variable duration content.
3003
3004
    Only 2 subtitles formats:
3005
    - Xsub from DivX
3006
        Samples are prefixed with a text formatted timestamp containing
3007
        start and stop times.
3008
        Track index provides sample location.
3009
        Chunk position is meaningless. All timings are within sample.
3010
    * - Txt
3011
        Samples are stored in a similar format as Xsub, but regrouped in a
3012
        single sample with metadata header. Location found using track index.
3013
        Those are extracted and exposed as attachment.
3014
        This track has to be ignored for playback.
3015
*/
3016
static void AVI_ExtractSubtitle( demux_t *p_demux,
3017
                                 unsigned int i_stream,
3018
                                 avi_chunk_list_t *p_strl,
3019
                                 avi_chunk_STRING_t *p_strn )
3020
198
{
3021
198
    demux_sys_t *p_sys = p_demux->p_sys;
3022
198
    block_t *p_block = NULL;
3023
198
    input_attachment_t *p_attachment = NULL;
3024
198
    char *psz_description = NULL;
3025
198
    avi_chunk_indx_t *p_indx = NULL;
3026
3027
198
    if( !p_sys->b_seekable )
3028
0
        goto exit;
3029
3030
198
    p_indx = AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0, false );
3031
198
    avi_chunk_t ck;
3032
198
    int64_t  i_position;
3033
198
    unsigned i_size;
3034
198
    if( p_indx )
3035
13
    {
3036
13
        if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES &&
3037
13
            p_indx->i_entriesinuse > 0 )
3038
3
        {
3039
3
            if( vlc_stream_Seek( p_demux->s, p_indx->idx.super[0].i_offset ) ||
3040
3
                AVI_ChunkRead( p_demux->s, &ck, NULL  ) ||
3041
3
                ck.common.i_chunk_fourcc != AVIFOURCC_indx )
3042
2
                goto exit;
3043
1
            p_indx = &ck.indx;
3044
1
        }
3045
3046
11
        if( p_indx->i_indextype != AVI_INDEX_OF_CHUNKS ||
3047
11
            p_indx->i_entriesinuse != 1 ||
3048
11
            p_indx->i_indexsubtype != 0 )
3049
8
            goto exit;
3050
3051
3
        i_position  = p_indx->i_baseoffset +
3052
3
                      p_indx->idx.std[0].i_offset - 8;
3053
3
        i_size      = (p_indx->idx.std[0].i_size & 0x7fffffff) + 8;
3054
3
    }
3055
185
    else
3056
185
    {
3057
185
        avi_chunk_idx1_t *p_idx1;
3058
185
        uint64_t         i_offset;
3059
3060
185
        if( AVI_IndexFind_idx1( p_demux, &p_idx1, &i_offset ) )
3061
37
            goto exit;
3062
3063
148
        i_size = 0;
3064
9.59k
        for( unsigned i = 0; i < p_idx1->i_entry_count; i++ )
3065
9.45k
        {
3066
9.45k
            const idx1_entry_t *e = &p_idx1->entry[i];
3067
9.45k
            enum es_format_category_e i_cat;
3068
9.45k
            unsigned i_stream_idx;
3069
3070
9.45k
            AVI_ParseStreamHeader( e->i_fourcc, &i_stream_idx, &i_cat );
3071
9.45k
            if( i_cat == SPU_ES && i_stream_idx == i_stream )
3072
12
            {
3073
12
                i_position = e->i_pos + i_offset;
3074
12
                i_size     = e->i_length + 8;
3075
12
                break;
3076
12
            }
3077
9.45k
        }
3078
148
        if( i_size <= 0 )
3079
136
            goto exit;
3080
148
    }
3081
3082
    /* */
3083
15
    if( i_size > 10000000 )
3084
6
    {
3085
6
        msg_Dbg( p_demux, "Attached subtitle too big: %u", i_size );
3086
6
        goto exit;
3087
6
    }
3088
3089
9
    if( vlc_stream_Seek( p_demux->s, i_position ) )
3090
0
        goto exit;
3091
9
    p_block = vlc_stream_Block( p_demux->s, i_size );
3092
9
    if( !p_block )
3093
4
        goto exit;
3094
3095
    /* Parse packet header */
3096
5
    const uint8_t *p = p_block->p_buffer;
3097
5
    if( i_size < 8 || p[2] != 't' || p[3] != 'x' )
3098
3
        goto exit;
3099
2
    p += 8;
3100
2
    i_size -= 8;
3101
3102
    /* Parse subtitle chunk header */
3103
2
    if( i_size < 11 || memcmp( p, "GAB2", 4 ) ||
3104
2
        p[4] != 0x00 || GetWLE( &p[5] ) != 0x2 )
3105
2
        goto exit;
3106
0
    const unsigned i_name = GetDWLE( &p[7] );
3107
0
    if( 11 + i_size <= i_name )
3108
0
        goto exit;
3109
0
    if( i_name > 0 )
3110
0
        psz_description = FromCharset( "UTF-16LE", &p[11], i_name );
3111
0
    p += 11 + i_name;
3112
0
    i_size -= 11 + i_name;
3113
0
    if( i_size < 6 || GetWLE( &p[0] ) != 0x04 )
3114
0
        goto exit;
3115
0
    const unsigned i_payload = GetDWLE( &p[2] );
3116
0
    if( i_size - 6 < i_payload || i_payload == 0 )
3117
0
        goto exit;
3118
0
    p += 6;
3119
0
    i_size -= 6;
3120
3121
0
    if( !psz_description )
3122
0
        psz_description = p_strn && p_strn->p_str ? FromACP( p_strn->p_str ) : NULL;
3123
0
    char *psz_name;
3124
0
    if( asprintf( &psz_name, "subtitle%d.srt", p_sys->i_attachment ) <= 0 )
3125
0
        psz_name = NULL;
3126
0
    p_attachment = vlc_input_attachment_New( psz_name,
3127
0
                                             "application/x-srt",
3128
0
                                             psz_description,
3129
0
                                             p, i_payload );
3130
0
    if( p_attachment )
3131
0
        TAB_APPEND( p_sys->i_attachment, p_sys->attachment, p_attachment );
3132
0
    free( psz_name );
3133
3134
198
exit:
3135
198
    free( psz_description );
3136
3137
198
    if( p_block )
3138
5
        block_Release( p_block );
3139
3140
198
    if( p_attachment )
3141
198
        msg_Dbg( p_demux, "Loaded an embedded subtitle" );
3142
198
    else
3143
198
        msg_Warn( p_demux, "Failed to load an embedded subtitle" );
3144
3145
198
    if( p_indx == &ck.indx )
3146
1
        AVI_ChunkClean( p_demux->s, &ck );
3147
198
}
3148
3149
static avi_track_t * AVI_GetVideoTrackForXsub( demux_sys_t *p_sys )
3150
0
{
3151
0
    for( unsigned i = 0; i < p_sys->i_track; i++ )
3152
0
    {
3153
0
        avi_track_t *p_stream = p_sys->track[i];
3154
0
        if( p_stream->b_activated &&
3155
0
            p_stream->fmt.i_cat == VIDEO_ES &&
3156
0
            p_stream->idx.i_size )
3157
0
            return p_stream;
3158
0
    }
3159
0
    return NULL;
3160
0
}
3161
3162
static int AVI_SeekSubtitleTrack( demux_sys_t *p_sys, avi_track_t *tk )
3163
0
{
3164
0
    if( tk->fmt.i_codec != FOURCC_DXSB )
3165
0
        return VLC_EGENERIC;
3166
3167
0
    const avi_track_t *p_videotk = AVI_GetVideoTrackForXsub( p_sys );
3168
0
    if( !p_videotk )
3169
0
        return VLC_EGENERIC;
3170
    /* Seek into SPU index using video track */
3171
3172
0
    unsigned idx = p_videotk->i_idxposc < p_videotk->idx.i_size
3173
0
            ? p_videotk->i_idxposc : p_videotk->idx.i_size - 1;
3174
0
    uint64_t i_pos = p_videotk->idx.p_entry[idx].i_pos;
3175
    /* invalidate sample timestamp */
3176
0
    tk->i_next_embedded_time = VLC_TICK_INVALID;
3177
0
    tk->i_last_embedded_endtime = VLC_TICK_INVALID;
3178
0
    for( tk->i_idxposc = 0; tk->i_idxposc<tk->idx.i_size; tk->i_idxposc++ )
3179
0
    {
3180
        /* match next pos, or closest -256KB sample */
3181
0
        if( tk->idx.p_entry[tk->i_idxposc].i_pos > i_pos )
3182
0
        {
3183
0
            tk->b_eof = false;
3184
0
            break;
3185
0
        }
3186
0
        else if( tk->idx.p_entry[tk->i_idxposc].i_pos + (1 << 28) <= i_pos )
3187
0
        {
3188
0
            tk->b_eof = false;
3189
0
        }
3190
0
    }
3191
0
    tk->b_eof = tk->i_idxposc == tk->idx.i_size;
3192
0
    if(!tk->b_eof)
3193
0
        tk->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY;
3194
3195
0
    return VLC_SUCCESS;
3196
0
}
3197
3198
/*****************************************************************************
3199
 * Stream management
3200
 *****************************************************************************/
3201
static int AVI_TrackStopFinishedStreams( demux_t *p_demux )
3202
19.1M
{
3203
19.1M
    demux_sys_t *p_sys = p_demux->p_sys;
3204
19.1M
    unsigned int i;
3205
19.1M
    int b_end = true;
3206
3207
56.0M
    for( i = 0; i < p_sys->i_track; i++ )
3208
36.8M
    {
3209
36.8M
        avi_track_t *tk = p_sys->track[i];
3210
36.8M
        if( tk->i_idxposc >= tk->idx.i_size )
3211
13.7M
        {
3212
13.7M
            tk->b_eof = true;
3213
13.7M
        }
3214
23.0M
        else
3215
23.0M
        {
3216
23.0M
            b_end = false;
3217
23.0M
        }
3218
36.8M
    }
3219
19.1M
    return( b_end );
3220
19.1M
}
3221
3222
/****************************************************************************
3223
 * AVI_MovieGetLength give max streams length in ticks
3224
 ****************************************************************************/
3225
static vlc_tick_t  AVI_MovieGetLength( demux_t *p_demux )
3226
11.2k
{
3227
11.2k
    demux_sys_t  *p_sys = p_demux->p_sys;
3228
11.2k
    vlc_tick_t   i_maxlength = 0;
3229
11.2k
    unsigned int i;
3230
3231
28.5k
    for( i = 0; i < p_sys->i_track; i++ )
3232
17.2k
    {
3233
17.2k
        avi_track_t *tk = p_sys->track[i];
3234
17.2k
        vlc_tick_t i_length;
3235
3236
        /* fix length for each stream */
3237
17.2k
        if( tk->idx.i_size < 1 || !tk->idx.p_entry )
3238
16.2k
        {
3239
16.2k
            continue;
3240
16.2k
        }
3241
3242
1.02k
        if( tk->i_samplesize )
3243
700
        {
3244
700
            i_length = AVI_GetDPTS( tk,
3245
700
                                    tk->idx.p_entry[tk->idx.i_size-1].i_lengthtotal +
3246
700
                                        tk->idx.p_entry[tk->idx.i_size-1].i_length );
3247
700
        }
3248
327
        else
3249
327
        {
3250
327
            i_length = AVI_GetDPTS( tk, tk->idx.i_size );
3251
327
        }
3252
3253
1.02k
        msg_Dbg( p_demux,
3254
1.02k
                 "stream[%d] length:%"PRId64" (based on index)",
3255
1.02k
                 i,
3256
1.02k
                 SEC_FROM_VLC_TICK(i_length) );
3257
1.02k
        i_maxlength = __MAX( i_maxlength, i_length );
3258
1.02k
    }
3259
3260
11.2k
    return i_maxlength;
3261
11.2k
}