Coverage Report

Created: 2025-07-11 07:16

/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
968
{
101
968
    return FromCharset(vlc_pgettext("GetACP", "CP1252"), str, strlen(str));
102
968
}
103
104
29
#define IGNORE_ES DATA_ES
105
10.4k
#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
19.5M
#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
876
#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
7.32k
{
270
7.32k
    switch (biCompression)
271
7.32k
    {
272
1
        case QNAP_FCC_w264:
273
65
        case QNAP_FCC_q264:
274
172
        case QNAP_FCC_Q264:
275
173
        case QNAP_FCC_wMP4:
276
191
        case QNAP_FCC_qMP4:
277
192
        case QNAP_FCC_QMP4:
278
194
        case QNAP_FCC_wIVG:
279
195
        case QNAP_FCC_qIVG:
280
196
        case QNAP_FCC_QIVG:
281
196
            return true;
282
7.12k
        default:
283
7.12k
            return false;
284
7.32k
    }
285
7.32k
}
286
287
20.5k
#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.81k
{
291
5.81k
    unsigned t[8];
292
5.81k
    char buffer[XSUB_HEADER_SIZE + 1];
293
5.81k
    memcpy( buffer, p_buf, XSUB_HEADER_SIZE );
294
5.81k
    buffer[XSUB_HEADER_SIZE] = '\0';
295
5.81k
    if( sscanf( buffer, "[%u:%2u:%2u.%3u-%u:%2u:%2u.%3u]",
296
5.81k
                &t[0], &t[1], &t[2], &t[3], &t[4], &t[5], &t[6], &t[7] ) != 8 )
297
5.81k
        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.81k
}
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.62k
{
308
8.62k
    ssize_t i_ret = vlc_stream_Peek( s, pp_peek, i_skip + i_peek );
309
8.62k
    *pp_peek += i_skip;
310
8.62k
    if ( i_ret < 0 || (size_t) i_ret != i_skip + i_peek )
311
2.92k
        return VLC_EGENERIC;
312
5.69k
    return VLC_SUCCESS;
313
8.62k
}
314
315
static vlc_tick_t AVI_GetXsubSampleTimeAt( stream_t *s, uint64_t pos )
316
8.62k
{
317
8.62k
    const uint8_t *p_peek;
318
8.62k
    vlc_tick_t i_nzstart, i_nzend;
319
8.62k
    if( vlc_stream_Seek( s, pos ) != VLC_SUCCESS ||
320
8.62k
        AVI_PeekSample( s, 8, &p_peek, XSUB_HEADER_SIZE ) ||
321
8.62k
        ExtractXsubSampleInfo( p_peek, &i_nzstart, &i_nzend ) )
322
8.62k
        return VLC_TICK_INVALID;
323
0
    return VLC_TICK_0 + i_nzstart;
324
8.62k
}
325
326
/*****************************************************************************
327
 * Close: frees unused data
328
 *****************************************************************************/
329
static void Close ( vlc_object_t * p_this )
330
12.3k
{
331
12.3k
    demux_t *    p_demux = (demux_t *)p_this;
332
12.3k
    demux_sys_t *p_sys = p_demux->p_sys  ;
333
334
27.9k
    for( unsigned int i = 0; i < p_sys->i_track; i++ )
335
15.6k
    {
336
15.6k
        if( p_sys->track[i] )
337
15.6k
        {
338
15.6k
            es_format_Clean( &p_sys->track[i]->fmt );
339
15.6k
            avi_index_Clean( &p_sys->track[i]->idx );
340
15.6k
            free( p_sys->track[i] );
341
15.6k
        }
342
15.6k
    }
343
12.3k
    free( p_sys->track );
344
345
12.3k
    AVI_ChunkFreeRoot( p_demux->s, &p_sys->ck_root );
346
12.3k
    if( p_sys->meta )
347
10.4k
        vlc_meta_Delete( p_sys->meta );
348
349
12.3k
    for( unsigned i = 0; i < p_sys->i_attachment; i++)
350
0
        vlc_input_attachment_Release(p_sys->attachment[i]);
351
12.3k
    free(p_sys->attachment);
352
353
12.3k
    free( p_sys );
354
12.3k
}
355
356
/*****************************************************************************
357
 * Open: check file and initializes AVI structures
358
 *****************************************************************************/
359
static int Open( vlc_object_t * p_this )
360
12.3k
{
361
12.3k
    demux_t  *p_demux = (demux_t *)p_this;
362
12.3k
    demux_sys_t     *p_sys;
363
364
12.3k
    bool       b_index = false, b_aborted = false;
365
12.3k
    int              i_do_index;
366
367
12.3k
    avi_chunk_list_t    *p_riff;
368
12.3k
    avi_chunk_list_t    *p_hdrl, *p_movi;
369
12.3k
    avi_chunk_avih_t    *p_avih;
370
371
12.3k
    unsigned int i_track;
372
12.3k
    unsigned int i_peeker;
373
374
12.3k
    const uint8_t *p_peek;
375
376
    /* Is it an avi file ? */
377
12.3k
    if( vlc_stream_Peek( p_demux->s, &p_peek, 200 ) < 200 )
378
21
        return VLC_EGENERIC;
379
380
152k
    for( i_peeker = 0; i_peeker < 188; i_peeker++ )
381
152k
    {
382
152k
        if( !strncmp( (char *)&p_peek[0], "RIFF", 4 ) && !strncmp( (char *)&p_peek[8], "AVI ", 4 ) )
383
12.2k
            break;
384
140k
        if( !strncmp( (char *)&p_peek[0], "ON2 ", 4 ) && !strncmp( (char *)&p_peek[8], "ON2f", 4 ) )
385
71
            break;
386
140k
        p_peek++;
387
140k
    }
388
12.3k
    if( i_peeker == 188 )
389
34
    {
390
34
        return VLC_EGENERIC;
391
34
    }
392
393
12.3k
    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
12.3k
    p_sys = p_demux->p_sys = calloc( 1, sizeof(demux_sys_t) );
398
12.3k
    if( unlikely(!p_sys) )
399
0
        return VLC_EGENERIC;
400
12.3k
    p_sys->b_odml   = false;
401
12.3k
    p_sys->meta     = NULL;
402
12.3k
    TAB_INIT(p_sys->i_track, p_sys->track);
403
12.3k
    TAB_INIT(p_sys->i_attachment, p_sys->attachment);
404
405
12.3k
    vlc_stream_Control( p_demux->s, STREAM_CAN_FASTSEEK,
406
12.3k
                        &p_sys->b_fastseekable );
407
12.3k
    vlc_stream_Control( p_demux->s, STREAM_CAN_SEEK, &p_sys->b_seekable );
408
409
12.3k
    p_sys->b_interleaved = var_InheritBool( p_demux, "avi-interleaved" );
410
411
12.3k
    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
12.3k
    if( AVI_ChunkCount( &p_sys->ck_root, AVIFOURCC_RIFF, true ) > 1 )
419
197
    {
420
197
        unsigned int i_count =
421
197
            AVI_ChunkCount( &p_sys->ck_root, AVIFOURCC_RIFF, true );
422
423
197
        msg_Warn( p_demux, "multiple riff -> OpenDML ?" );
424
2.74k
        for( unsigned i = 1; i < i_count; i++ )
425
2.54k
        {
426
2.54k
            avi_chunk_list_t *p_sysx;
427
428
2.54k
            p_sysx = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, i, true );
429
2.54k
            if( p_sysx && p_sysx->i_type == AVIFOURCC_AVIX )
430
4
            {
431
4
                msg_Warn( p_demux, "detected OpenDML file" );
432
4
                p_sys->b_odml = true;
433
4
                break;
434
4
            }
435
2.54k
        }
436
197
    }
437
438
12.3k
    p_riff  = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0, true );
439
12.3k
    p_hdrl  = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0, true );
440
12.3k
    p_movi  = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0, true );
441
12.3k
    if( !p_movi )
442
2.08k
        p_movi  = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_movi, 0, true );
443
444
12.3k
    if( !p_hdrl || !p_movi )
445
1.83k
    {
446
1.83k
        msg_Err( p_demux, "invalid file: cannot find hdrl or movi chunks" );
447
1.83k
        goto error;
448
1.83k
    }
449
450
10.4k
    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
10.4k
    i_track = AVI_ChunkCount( p_hdrl, AVIFOURCC_strl, true );
456
10.4k
    if( p_avih->i_streams != i_track )
457
8.81k
    {
458
8.81k
        msg_Warn( p_demux,
459
8.81k
                  "found %d stream but %d are declared",
460
8.81k
                  i_track, p_avih->i_streams );
461
8.81k
    }
462
10.4k
    if( i_track == 0 )
463
49
    {
464
49
        msg_Err( p_demux, "no stream defined!" );
465
49
        goto error;
466
49
    }
467
468
    /* print information on streams */
469
10.4k
    msg_Dbg( p_demux, "AVIH: %d stream, flags %s%s%s%s ",
470
10.4k
             i_track,
471
10.4k
             p_avih->i_flags&AVIF_HASINDEX?" HAS_INDEX":"",
472
10.4k
             p_avih->i_flags&AVIF_MUSTUSEINDEX?" MUST_USE_INDEX":"",
473
10.4k
             p_avih->i_flags&AVIF_ISINTERLEAVED?" IS_INTERLEAVED":"",
474
10.4k
             p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" );
475
476
10.4k
    p_sys->b_interleaved |= (p_avih->i_flags & AVIF_ISINTERLEAVED);
477
478
    /* Set callbacks */
479
10.4k
    p_demux->pf_control = Control;
480
481
10.4k
    if( p_sys->b_fastseekable )
482
10.4k
    {
483
10.4k
        p_demux->pf_demux = Demux_Seekable;
484
10.4k
        p_sys->i_read_increment = READ_LENGTH;
485
10.4k
    }
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
10.4k
    AVI_MetaLoad( p_demux, p_riff, p_avih );
510
10.4k
    p_sys->i_avih_flags = p_avih->i_flags;
511
512
    /* now read info on each stream and create ES */
513
28.7k
    for( unsigned i = 0 ; i < i_track; i++ )
514
18.3k
    {
515
18.3k
        avi_track_t           *tk     = calloc( 1, sizeof( avi_track_t ) );
516
18.3k
        if( unlikely( !tk ) )
517
0
            goto error;
518
519
18.3k
        avi_chunk_list_t      *p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i, true );
520
18.3k
        avi_chunk_strh_t      *p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0, false );
521
18.3k
        avi_chunk_STRING_t    *p_strn = AVI_ChunkFind( p_strl, AVIFOURCC_strn, 0, false );
522
18.3k
        avi_chunk_strf_auds_t *p_auds = NULL;
523
18.3k
        avi_chunk_strf_vids_t *p_vids = NULL;
524
525
18.3k
        tk->b_eof = false;
526
18.3k
        tk->b_activated = true;
527
528
18.3k
        p_vids = (avi_chunk_strf_vids_t*)AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0, false );
529
18.3k
        p_auds = (avi_chunk_strf_auds_t*)p_vids;
530
531
18.3k
        if( p_strl == NULL || p_strh == NULL || p_vids == NULL )
532
1.95k
        {
533
1.95k
            msg_Warn( p_demux, "stream[%d] incomplete", i );
534
1.95k
            free( tk );
535
1.95k
            continue;
536
1.95k
        }
537
538
16.4k
        tk->i_rate  = p_strh->i_rate;
539
16.4k
        tk->i_scale = p_strh->i_scale;
540
16.4k
        tk->i_samplesize = p_strh->i_samplesize;
541
16.4k
        msg_Dbg( p_demux, "stream[%u] rate:%u scale:%u samplesize:%u",
542
16.4k
                i, tk->i_rate, tk->i_scale, tk->i_samplesize );
543
544
16.4k
        switch( p_strh->i_type )
545
16.4k
        {
546
7.77k
            case( AVIFOURCC_auds ):
547
7.77k
            {
548
7.77k
                es_format_Init( &tk->fmt, AUDIO_ES, 0 );
549
550
7.77k
                if( p_auds->p_wf->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
551
7.77k
                    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
7.75k
                else
557
7.75k
                    tk->fmt.i_codec = AVI_FourccGetCodec( AUDIO_ES, p_auds->p_wf->wFormatTag );
558
559
7.77k
                tk->i_blocksize = p_auds->p_wf->nBlockAlign;
560
561
                /* Fix blocksize == 0 and force interleaving PCM chunks samplesize == 0 */
562
7.77k
                if( tk->i_samplesize == 0 || tk->i_blocksize == 0 )
563
3.87k
                {
564
3.87k
                    vlc_fourcc_t i_codec = vlc_fourcc_GetCodecAudio( tk->fmt.i_codec,
565
3.87k
                                                                     p_auds->p_wf->wBitsPerSample );
566
3.87k
                    unsigned bps = aout_BitsPerSample( i_codec );
567
3.87k
                    if( bps > 0 ) /* PCM audio */
568
767
                    {
569
767
                        if( tk->i_blocksize == 0 )
570
617
                            tk->i_blocksize = bps * p_auds->p_wf->nChannels / 8;
571
767
                        if( tk->i_samplesize == 0 )
572
177
                            tk->i_samplesize = tk->i_blocksize;
573
767
                        tk->fmt.b_packetized = true;
574
767
                    }
575
3.10k
                    else if( tk->i_blocksize == 0 )
576
1.83k
                    {
577
1.83k
                        tk->i_blocksize = 1;
578
1.83k
                    }
579
3.87k
                }
580
3.89k
                else if( tk->i_samplesize != tk->i_blocksize )
581
3.62k
                {
582
3.62k
                    msg_Warn( p_demux, "track[%u] samplesize=%u and blocksize=%u are not equal."
583
3.62k
                                       "Using blocksize as a workaround.",
584
3.62k
                                       i, tk->i_samplesize, tk->i_blocksize );
585
3.62k
                    tk->i_samplesize = tk->i_blocksize;
586
3.62k
                }
587
588
                /* fix VBR decoding */
589
7.77k
                if( tk->fmt.i_codec == VLC_CODEC_VORBIS ||
590
7.77k
                    tk->fmt.i_codec == VLC_CODEC_FLAC )
591
1
                {
592
1
                    tk->i_blocksize = 0;
593
1
                }
594
595
7.77k
                if ( tk->fmt.i_codec == VLC_CODEC_MP4A )
596
278
                {
597
278
                    tk->i_samplesize = 0; /* ADTS/AAC VBR */
598
278
                }
599
600
                /* Fix broken scale/rate */
601
7.77k
                if ( tk->fmt.i_codec == VLC_CODEC_ADPCM_IMA_WAV &&
602
7.77k
                     tk->i_samplesize && tk->i_samplesize > tk->i_rate )
603
347
                {
604
347
                    tk->i_scale = 1017;
605
347
                    tk->i_rate = p_auds->p_wf->nSamplesPerSec;
606
347
                }
607
608
                /* From libavformat */
609
                /* Fix broken sample size (which is mp2 num samples / frame) #12722 */
610
7.77k
                if( tk->fmt.i_codec == VLC_CODEC_MPGA &&
611
7.77k
                    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
7.77k
                tk->fmt.audio.i_channels        = p_auds->p_wf->nChannels;
617
7.77k
                tk->fmt.audio.i_rate            = p_auds->p_wf->nSamplesPerSec;
618
7.77k
                tk->fmt.i_bitrate               = p_auds->p_wf->nAvgBytesPerSec*8;
619
7.77k
                tk->fmt.audio.i_blockalign      = p_auds->p_wf->nBlockAlign;
620
7.77k
                tk->fmt.audio.i_bitspersample   = p_auds->p_wf->wBitsPerSample;
621
7.77k
                tk->fmt.b_packetized            = !tk->i_blocksize;
622
623
7.77k
                avi_chunk_list_t *p_info = AVI_ChunkFind( p_riff, AVIFOURCC_INFO, 0, true );
624
7.77k
                if( p_info )
625
3.01k
                {
626
3.01k
                    int i_chunk = AVIFOURCC_IAS1 + ((i - 1) << 24);
627
3.01k
                    avi_chunk_STRING_t *p_lang = AVI_ChunkFind( p_info, i_chunk, 0, false );
628
3.01k
                    if( p_lang != NULL && p_lang->p_str != NULL )
629
0
                        tk->fmt.psz_language = FromACP( p_lang->p_str );
630
3.01k
                }
631
632
7.77k
                msg_Dbg( p_demux,
633
7.77k
                    "stream[%u] audio(0x%x - %s) %d channels %dHz %dbits",
634
7.77k
                    i, p_auds->p_wf->wFormatTag,
635
7.77k
                    vlc_fourcc_GetDescription(AUDIO_ES, tk->fmt.i_codec),
636
7.77k
                    p_auds->p_wf->nChannels,
637
7.77k
                    p_auds->p_wf->nSamplesPerSec,
638
7.77k
                    p_auds->p_wf->wBitsPerSample );
639
640
7.77k
                const size_t i_cboff = sizeof(WAVEFORMATEX);
641
7.77k
                const size_t i_incboff = ( p_auds->p_wf->wFormatTag == WAVE_FORMAT_EXTENSIBLE ) ?
642
7.74k
                                          sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX): 0;
643
7.77k
                if( p_auds->i_chunk_size >= i_cboff + p_auds->p_wf->cbSize &&
644
7.77k
                    p_auds->p_wf->cbSize > i_incboff )
645
237
                {
646
237
                    int i_extra = p_auds->p_wf->cbSize - i_incboff;
647
237
                    tk->fmt.p_extra = malloc( i_extra );
648
237
                    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
237
                    tk->fmt.i_extra = i_extra;
655
237
                    memcpy( tk->fmt.p_extra, ((uint8_t *)(&p_auds->p_wf[1])) + i_incboff, i_extra );
656
237
                }
657
7.77k
                break;
658
7.77k
            }
659
660
7.77k
            case( AVIFOURCC_vids ):
661
6.64k
            {
662
6.64k
                if( p_vids->p_bih->biCompression == FOURCC_DXSB )
663
47
                {
664
47
                   msg_Dbg( p_demux, "stream[%u] subtitles", i );
665
47
                   es_format_Init( &tk->fmt, SPU_ES, p_vids->p_bih->biCompression );
666
47
                   tk->fmt.subs.spu.i_original_frame_width = p_vids->p_bih->biWidth;
667
47
                   tk->fmt.subs.spu.i_original_frame_height = p_vids->p_bih->biHeight;
668
47
                   break;
669
47
                }
670
671
6.59k
                es_format_Init( &tk->fmt, VIDEO_ES, 0 );
672
673
6.59k
                if( ParseBitmapInfoHeader( p_vids->p_bih, p_vids->i_chunk_size, &tk->fmt,
674
6.59k
                                           &tk->bihprops ) != VLC_SUCCESS )
675
30
                {
676
30
                    es_format_Clean( &tk->fmt );
677
30
                    free( tk );
678
30
                    goto error;
679
30
                }
680
681
6.56k
                if( tk->fmt.i_codec == VLC_CODEC_MP4V &&
682
6.56k
                    !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
6.56k
                if( IsQNAPCodec( p_vids->p_bih->biCompression ) )
690
189
                {
691
189
                    tk->is_qnap = true;
692
189
                    tk->fmt.b_packetized = false;
693
189
                }
694
695
6.56k
                tk->i_samplesize = 0;
696
6.56k
                tk->fmt.video.i_frame_rate = tk->i_rate;
697
6.56k
                tk->fmt.video.i_frame_rate_base = tk->i_scale;
698
699
6.56k
                avi_chunk_vprp_t *p_vprp = AVI_ChunkFind( p_strl, AVIFOURCC_vprp, 0, false );
700
6.56k
                if( p_vprp )
701
17
                {
702
17
                    uint32_t i_frame_aspect_ratio = p_vprp->i_frame_aspect_ratio;
703
17
                    if( p_vprp->i_video_format_token >= 1 &&
704
17
                        p_vprp->i_video_format_token <= 4 )
705
3
                        i_frame_aspect_ratio = 0x00040003;
706
17
                    tk->fmt.video.i_sar_num = ((i_frame_aspect_ratio >> 16) & 0xffff) *
707
17
                                              tk->fmt.video.i_height;
708
17
                    tk->fmt.video.i_sar_den = ((i_frame_aspect_ratio >>  0) & 0xffff) *
709
17
                                              tk->fmt.video.i_width;
710
17
                }
711
712
6.56k
                msg_Dbg( p_demux, "stream[%u] video(%4.4s) %"PRIu32"x%"PRIu32" %dbpp %ffps",
713
6.56k
                         i, (char*)&p_vids->p_bih->biCompression,
714
6.56k
                         p_vids->p_bih->biWidth,
715
6.56k
                         (p_vids->p_bih->biHeight <= INT_MAX) ? p_vids->p_bih->biHeight
716
6.56k
                                                              : -1 * p_vids->p_bih->biHeight,
717
6.56k
                         p_vids->p_bih->biBitCount,
718
6.56k
                         (float)tk->i_rate/(float)tk->i_scale );
719
6.56k
                break;
720
6.59k
            }
721
722
188
            case( AVIFOURCC_txts):
723
188
                msg_Dbg( p_demux, "stream[%u] subtitle attachment", i );
724
188
                AVI_ExtractSubtitle( p_demux, i, p_strl, p_strn );
725
188
                free( tk );
726
188
                continue;
727
728
190
            case( AVIFOURCC_iavs):
729
1.36k
            case( AVIFOURCC_ivas):
730
1.36k
                msg_Dbg( p_demux, "stream[%u] iavs with handler %4.4s", i, (char *)&p_strh->i_handler );
731
1.36k
                es_format_Init( &tk->fmt, VIDEO_ES, AVI_FourccGetCodec( VIDEO_ES, p_strh->i_handler ) );
732
1.36k
                tk->i_samplesize = 0;
733
1.36k
                tk->i_dv_audio_rate = tk->fmt.i_codec == VLC_CODEC_DV ? -1 : 0;
734
735
1.36k
                tk->fmt.video.i_visible_width =
736
1.36k
                tk->fmt.video.i_width  = p_avih->i_width;
737
1.36k
                tk->fmt.video.i_visible_height =
738
1.36k
                tk->fmt.video.i_height = p_avih->i_height;
739
1.36k
                break;
740
741
3
            case( AVIFOURCC_mids):
742
3
                msg_Dbg( p_demux, "stream[%u] midi is UNSUPPORTED", i );
743
                /* fall through */
744
745
468
            default:
746
468
                msg_Warn( p_demux, "stream[%u] unknown type %4.4s", i, (char *)&p_strh->i_type );
747
468
                free( tk );
748
468
                continue;
749
16.4k
        }
750
751
15.7k
        if( tk->fmt.i_cat != SPU_ES &&
752
15.7k
           (!tk->i_scale || !tk->i_rate || !(tk->i_rate * CLOCK_FREQ / tk->i_scale)) )
753
139
        {
754
139
            msg_Warn( p_demux, "stream[%u] has invalid timescale", i );
755
139
            es_format_Clean(&tk->fmt);
756
139
            free( tk );
757
139
            continue;
758
139
        }
759
760
15.6k
        tk->fmt.i_id = i;
761
15.6k
        if( p_strn && p_strn->p_str )
762
14
            tk->fmt.psz_description = FromACP( p_strn->p_str );
763
15.6k
        tk->p_es = es_out_Add( p_demux->out, &tk->fmt );
764
15.6k
        TAB_APPEND( p_sys->i_track, p_sys->track, tk );
765
15.6k
    }
766
767
10.3k
    if( p_sys->i_track <= 0 )
768
263
    {
769
263
        msg_Err( p_demux, "no valid track" );
770
263
        goto error;
771
263
    }
772
773
10.1k
    i_do_index = var_InheritInteger( p_demux, "avi-index" );
774
10.1k
    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
10.1k
    else if( p_sys->b_seekable )
791
10.1k
    {
792
10.1k
        AVI_IndexLoad( p_demux );
793
10.1k
    }
794
795
    /* *** movie length in vlc_tick_t *** */
796
10.1k
    p_sys->i_length = AVI_MovieGetLength( p_demux );
797
798
    /* Check the index completeness */
799
10.1k
    unsigned int i_idx_totalframes = 0;
800
25.7k
    for( unsigned int i = 0; i < p_sys->i_track; i++ )
801
15.6k
    {
802
15.6k
        const avi_track_t *tk = p_sys->track[i];
803
15.6k
        if( tk->fmt.i_cat == VIDEO_ES && tk->idx.p_entry )
804
183
            i_idx_totalframes = __MAX(i_idx_totalframes, tk->idx.i_size);
805
15.6k
    }
806
10.1k
    if( i_idx_totalframes != p_avih->i_totalframes &&
807
10.1k
        p_sys->i_length < VLC_TICK_FROM_US( p_avih->i_totalframes *
808
10.1k
                                            p_avih->i_microsecperframe ) )
809
7.44k
    {
810
7.44k
        msg_Warn( p_demux, "broken or missing index, 'seek' will be "
811
7.44k
                           "approximative or will exhibit strange behavior" );
812
7.44k
        if( (i_do_index == 0 || i_do_index == 3) && !b_index )
813
7.44k
        {
814
7.44k
            if( !p_sys->b_fastseekable ) {
815
0
                b_index = true;
816
0
                goto aviindex;
817
0
            }
818
7.44k
            if( i_do_index == 0 )
819
7.44k
            {
820
7.44k
                const char *psz_msg = _(
821
7.44k
                    "Because this file index is broken or missing, "
822
7.44k
                    "seeking will not work correctly.\n"
823
7.44k
                    "VLC won't repair your file but can temporary fix this "
824
7.44k
                    "problem by building an index in memory.\n"
825
7.44k
                    "This step might take a long time on a large file.\n"
826
7.44k
                    "What do you want to do?");
827
7.44k
                switch( vlc_dialog_wait_question( p_demux,
828
7.44k
                                                  VLC_DIALOG_QUESTION_NORMAL,
829
7.44k
                                                  _("Do not play"),
830
7.44k
                                                  _("Build index then play"),
831
7.44k
                                                  _("Play as is"),
832
7.44k
                                                  _("Broken or missing Index"),
833
7.44k
                                                  "%s", psz_msg ) )
834
7.44k
                {
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
7.44k
                }
843
7.44k
            }
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
7.44k
        }
851
7.44k
    }
852
853
    /* fix some BeOS MediaKit generated file */
854
25.7k
    for( unsigned i = 0 ; i < p_sys->i_track; i++ )
855
15.6k
    {
856
15.6k
        avi_track_t         *tk = p_sys->track[i];
857
15.6k
        avi_chunk_list_t    *p_strl;
858
15.6k
        avi_chunk_strf_auds_t    *p_auds;
859
860
15.6k
        if( tk->fmt.i_cat != AUDIO_ES )
861
7.95k
        {
862
7.95k
            continue;
863
7.95k
        }
864
7.65k
        if( tk->idx.i_size < 1 ||
865
7.65k
            tk->i_scale != 1 ||
866
7.65k
            tk->i_samplesize != 0 )
867
7.65k
        {
868
7.65k
            continue;
869
7.65k
        }
870
4
        p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, tk->fmt.i_id, true );
871
4
        p_auds = AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0, false );
872
873
4
        if( p_auds &&
874
4
            p_auds->p_wf->wFormatTag != WAVE_FORMAT_PCM &&
875
4
            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
4
    }
893
894
10.1k
    if( p_sys->b_seekable )
895
10.1k
    {
896
        /* we have read all chunk so go back to movi */
897
10.1k
        if( vlc_stream_Seek( p_demux->s, p_movi->i_chunk_pos ) )
898
0
            goto error;
899
10.1k
    }
900
    /* Skip movi header */
901
10.1k
    if( vlc_stream_Read( p_demux->s, NULL, 12 ) != 12 )
902
0
        goto error;
903
904
10.1k
    p_sys->i_movi_begin = p_movi->i_chunk_pos;
905
10.1k
    return VLC_SUCCESS;
906
907
2.18k
error:
908
2.18k
    Close( p_this );
909
2.18k
    return b_aborted ? VLC_ETIMEOUT : VLC_EGENERIC;
910
10.1k
}
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
18.3M
{
919
    /* skip header */
920
18.3M
    if( i_header )
921
9.79M
    {
922
9.79M
        assert(i_header % 8 == 0);
923
9.79M
        ssize_t i_skip = vlc_stream_Read( p_demux->s, NULL, i_header );
924
9.79M
        if( i_skip < 0 || (size_t) i_skip < i_header )
925
573k
            return NULL;
926
9.79M
    }
927
928
    /* read size padded on word boundary */
929
17.8M
    uint32_t i_size = __EVEN(i_osize);
930
931
17.8M
    if( i_size == 0 )
932
518
        return block_Alloc(0); /* vlc_stream_Block can't read/alloc 0 sized */
933
934
17.8M
    block_t *p_frame = vlc_stream_Block( p_demux->s, i_size );
935
17.8M
    if ( !p_frame )
936
16.5M
        return p_frame;
937
938
1.22M
    if( i_osize == i_size - 1 )
939
1.19M
        p_frame->i_buffer--;
940
941
1.22M
    if( tk->fmt.i_codec == FOURCC_DXSB && p_frame->i_buffer > XSUB_HEADER_SIZE )
942
116
    {
943
116
        vlc_tick_t i_start, i_end;
944
116
        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
116
    }
951
952
1.22M
    if( tk->bihprops.i_stride > INT32_MAX - 3 )
953
243
    {
954
243
        p_frame->i_buffer = 0;
955
243
        return p_frame;
956
243
    }
957
958
1.22M
    const unsigned int i_stride_bytes = (tk->bihprops.i_stride + 3) & ~3;
959
960
1.22M
    if ( !tk->bihprops.i_stride || !i_stride_bytes )
961
1.22M
        return p_frame;
962
963
660
    if( p_frame->i_buffer < i_stride_bytes )
964
186
    {
965
186
        p_frame->i_buffer = 0;
966
186
        return p_frame;
967
186
    }
968
969
474
    if( !tk->bihprops.b_flipped )
970
108
    {
971
108
        const uint8_t *p_src = p_frame->p_buffer + i_stride_bytes;
972
108
        const uint8_t *p_end = p_frame->p_buffer + p_frame->i_buffer;
973
108
        uint8_t *p_dst = p_frame->p_buffer + tk->bihprops.i_stride;
974
975
108
        p_frame->i_buffer = tk->bihprops.i_stride;
976
977
4.45k
        while ( p_src + i_stride_bytes <= p_end )
978
4.34k
        {
979
4.34k
            memmove( p_dst, p_src, tk->bihprops.i_stride );
980
4.34k
            p_src += i_stride_bytes;
981
4.34k
            p_dst += tk->bihprops.i_stride;
982
4.34k
            p_frame->i_buffer += tk->bihprops.i_stride;
983
4.34k
        }
984
108
    }
985
366
    else
986
366
    {
987
366
        block_t *p_flippedframe = block_Alloc( p_frame->i_buffer );
988
366
        if ( !p_flippedframe )
989
0
        {
990
0
            block_Release( p_frame );
991
0
            return NULL;
992
0
        }
993
994
366
        unsigned int i_lines = p_frame->i_buffer / i_stride_bytes;
995
366
        const uint8_t *p_src = p_frame->p_buffer + i_lines * i_stride_bytes;
996
366
        uint8_t *p_dst = p_flippedframe->p_buffer;
997
998
366
        p_flippedframe->i_buffer = 0;
999
1000
43.4k
        while ( i_lines-- > 0 )
1001
43.1k
        {
1002
43.1k
            p_src -= i_stride_bytes;
1003
43.1k
            memcpy( p_dst, p_src, tk->bihprops.i_stride );
1004
43.1k
            p_dst += tk->bihprops.i_stride;
1005
43.1k
            p_flippedframe->i_buffer += tk->bihprops.i_stride;
1006
43.1k
        }
1007
1008
366
        block_Release( p_frame );
1009
366
        p_frame = p_flippedframe;
1010
366
    }
1011
1012
474
    return p_frame;
1013
474
}
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.22M
{
1020
1.22M
    demux_sys_t *p_sys = p_demux->p_sys;
1021
1022
1.22M
    if( tk->fmt.i_cat != VIDEO_ES )
1023
1.21M
        p_frame->i_dts = p_frame->i_pts;
1024
6.97k
    else
1025
6.97k
    {
1026
6.97k
        p_frame->i_dts = p_frame->i_pts;
1027
6.97k
        p_frame->i_pts = VLC_TICK_INVALID;
1028
6.97k
    }
1029
1030
1.22M
    if( tk->i_dv_audio_rate )
1031
193
        AVI_DvHandleAudio( p_demux, tk, p_frame );
1032
1033
    /* Strip 3rd party header */
1034
1.22M
    if( tk->is_qnap )
1035
628
    {
1036
628
        if( p_frame->i_buffer >= QNAP_VIDEO_HEADER_SIZE )
1037
124
        {
1038
124
            const uint8_t *p = p_frame->p_buffer;
1039
            /* Check header is really there */
1040
124
            vlc_fourcc_t fcc = VLC_FOURCC(p[0],p[1],p[2],p[3]);
1041
            /* Parse QNAP header */
1042
124
            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
124
            p_frame->i_buffer -= QNAP_VIDEO_HEADER_SIZE;
1057
124
            p_frame->p_buffer += QNAP_VIDEO_HEADER_SIZE;
1058
124
        }
1059
628
    }
1060
1061
1.22M
    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.22M
    if( tk->p_es )
1068
1.22M
        es_out_Send( p_demux->out, tk->p_es, p_frame );
1069
0
    else
1070
0
        block_Release( p_frame );
1071
1.22M
}
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
204M
{
1082
204M
    demux_sys_t *p_sys = p_demux->p_sys;
1083
1084
204M
    unsigned int i_track_count = 0;
1085
1086
    /* detect new selected/unselected streams */
1087
459M
    for( unsigned int i = 0; i < p_sys->i_track; i++ )
1088
255M
    {
1089
255M
        avi_track_t *tk = p_sys->track[i];
1090
255M
        bool  b = false;
1091
1092
255M
        es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b );
1093
255M
        if( tk->p_es_dv_audio )
1094
352
        {
1095
352
            bool b_extra = false;
1096
352
            es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es_dv_audio, &b_extra );
1097
352
            b |= b_extra;
1098
352
        }
1099
255M
        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
255M
        else if( !b && tk->b_activated )
1108
0
        {
1109
0
            tk->b_activated = false;
1110
0
        }
1111
255M
        if( b )
1112
255M
        {
1113
255M
            i_track_count++;
1114
255M
        }
1115
255M
    }
1116
1117
204M
    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
204M
    es_out_SetPCR( p_demux->out, VLC_TICK_0 + p_sys->i_time );
1132
204M
    p_sys->i_time += p_sys->i_read_increment;
1133
1134
    /* init toread */
1135
459M
    for( unsigned i = 0; i < p_sys->i_track; i++ )
1136
255M
    {
1137
255M
        avi_track_t *tk = p_sys->track[i];
1138
1139
255M
        tk->demuxctx.b_ok = tk->b_activated && !tk->b_eof;
1140
255M
        if( tk->i_idxposc < tk->idx.i_size )
1141
207M
        {
1142
207M
            tk->demuxctx.i_posf = tk->idx.p_entry[tk->i_idxposc].i_pos;
1143
207M
           if( tk->i_idxposb > 0 )
1144
173M
           {
1145
173M
                tk->demuxctx.i_posf += 8 + tk->i_idxposb;
1146
173M
           }
1147
207M
        }
1148
47.5M
        else
1149
47.5M
        {
1150
47.5M
            tk->demuxctx.i_posf = -1;
1151
47.5M
        }
1152
1153
        /* Xsub specific. There's no possible chunk/byte<->time */
1154
255M
        if( tk->fmt.i_codec == FOURCC_DXSB )
1155
36.5k
        {
1156
            /* load spu times */
1157
36.5k
            if( tk->i_next_embedded_time == VLC_TICK_INVALID && tk->demuxctx.i_posf != -1 )
1158
8.62k
                tk->i_next_embedded_time = AVI_GetXsubSampleTimeAt(
1159
8.62k
                            p_demux->s, tk->idx.p_entry[ tk->i_idxposc].i_pos );
1160
36.5k
            vlc_tick_t i_reftime = tk->i_next_embedded_time != VLC_TICK_INVALID
1161
36.5k
                                 ? tk->i_next_embedded_time : tk->i_last_embedded_endtime;
1162
36.5k
            if( i_reftime != VLC_TICK_INVALID &&
1163
36.5k
                p_sys->i_time - i_reftime  >  VLC_TICK_FROM_SEC(-2) )
1164
0
                tk->demuxctx.i_toread = 1;
1165
36.5k
            else
1166
36.5k
                tk->demuxctx.i_toread = -1;
1167
36.5k
            continue;
1168
36.5k
        }
1169
1170
255M
        vlc_tick_t i_dpts = p_sys->i_time - AVI_GetPTS( tk );
1171
1172
255M
        if( tk->i_samplesize )
1173
234M
        {
1174
234M
            tk->demuxctx.i_toread = AVI_PTSToByte( tk, i_dpts );
1175
234M
        }
1176
20.5M
        else if ( i_dpts > VLC_TICK_FROM_SEC(-2) ) /* don't send a too early dts (low fps video) */
1177
20.5M
        {
1178
20.5M
            int64_t i_chunks_count = AVI_PTSToChunk( tk, i_dpts );
1179
20.5M
            if( i_dpts > 0 && AVI_GetDPTS( tk, i_chunks_count ) < i_dpts )
1180
19.8M
            {
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
19.8M
                i_chunks_count++;
1184
19.8M
            }
1185
20.5M
            tk->demuxctx.i_toread = i_chunks_count;
1186
20.5M
        }
1187
36.9k
        else
1188
36.9k
            tk->demuxctx.i_toread = -1;
1189
255M
    }
1190
1191
204M
    for( ;; )
1192
222M
    {
1193
222M
        bool b_done = true;
1194
222M
        block_t         *p_frame;
1195
222M
        int64_t i_pos = -1;
1196
222M
        unsigned int i_track = 0;
1197
1198
        /* search for first chunk to be read */
1199
514M
        for( unsigned i = 0; i < p_sys->i_track; i++ )
1200
291M
        {
1201
291M
            avi_track_t *tk = p_sys->track[i];
1202
291M
            if( !tk->demuxctx.b_ok ||
1203
291M
                ( p_sys->b_fastseekable && p_sys->b_interleaved &&
1204
248M
                  AVI_GetDPTS( tk, tk->demuxctx.i_toread ) <= -p_sys->i_read_increment ) )
1205
52.5M
            {
1206
52.5M
                continue;
1207
52.5M
            }
1208
1209
239M
            if( tk->demuxctx.i_toread > 0 )
1210
35.5M
            {
1211
35.5M
                b_done = false; /* not yet finished */
1212
1213
35.5M
                if( tk->demuxctx.i_posf > 0 )
1214
18.5M
                {
1215
18.5M
                    if( i_pos == -1 || i_pos > tk->demuxctx.i_posf )
1216
18.4M
                    {
1217
18.4M
                        i_track = i;
1218
18.4M
                        i_pos = tk->demuxctx.i_posf;
1219
18.4M
                    }
1220
18.5M
                }
1221
35.5M
            }
1222
239M
        }
1223
1224
222M
        if( b_done )
1225
188M
        {
1226
194M
            for( unsigned i = 0; i < p_sys->i_track; i++ )
1227
194M
            {
1228
194M
                const avi_track_t *tk = p_sys->track[i];
1229
194M
                if( tk->demuxctx.b_ok && tk->demuxctx.i_toread >= 0 )
1230
188M
                    return VLC_DEMUXER_SUCCESS;
1231
194M
            }
1232
1.91k
            msg_Warn( p_demux, "all tracks have failed, exiting..." );
1233
1.91k
            return VLC_DEMUXER_EOF;
1234
188M
        }
1235
1236
34.0M
        if( i_pos == -1 )
1237
15.7M
        {
1238
15.7M
            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
15.7M
            if( p_sys->b_seekable && p_sys->i_movi_lastchunk_pos >= p_sys->i_movi_begin + 12 )
1243
14.7M
            {
1244
14.7M
                if (vlc_stream_Seek(p_demux->s, p_sys->i_movi_lastchunk_pos))
1245
0
                    return VLC_DEMUXER_EGENERIC;
1246
1247
14.7M
                if( AVI_PacketNext( p_demux ) )
1248
14.4M
                {
1249
14.4M
                    return( AVI_TrackStopFinishedStreams( p_demux ) ? 0 : 1 );
1250
14.4M
                }
1251
14.7M
            }
1252
987k
            else
1253
987k
            {
1254
987k
                if (vlc_stream_Seek(p_demux->s, p_sys->i_movi_begin + 12))
1255
0
                    return VLC_DEMUXER_EGENERIC;
1256
987k
            }
1257
1258
1.29M
            for( ;; )
1259
1.47M
            {
1260
1.47M
                avi_packet_t avi_pk;
1261
1262
1.47M
                if( AVI_PacketGetHeader( p_demux, &avi_pk ) )
1263
127k
                {
1264
127k
                    msg_Warn( p_demux,
1265
127k
                             "cannot get packet header, track disabled" );
1266
127k
                    return( AVI_TrackStopFinishedStreams( p_demux ) ? 0 : 1 );
1267
127k
                }
1268
1.35M
                if( avi_pk.i_stream >= p_sys->i_track ||
1269
1.35M
                    ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )
1270
1.33M
                {
1271
1.33M
                    if( AVI_PacketNext( p_demux ) )
1272
1.15M
                    {
1273
1.15M
                        msg_Warn( p_demux,
1274
1.15M
                                  "cannot skip packet, track disabled" );
1275
1.15M
                        return( AVI_TrackStopFinishedStreams( p_demux ) ? 0 : 1 );
1276
1.15M
                    }
1277
1278
182k
                    if( !++i_loop_count )
1279
182k
                         msg_Warn( p_demux, "don't seem to find any data..." );
1280
182k
                    continue;
1281
1.33M
                }
1282
11.4k
                else
1283
11.4k
                {
1284
11.4k
                    i_track = avi_pk.i_stream;
1285
11.4k
                    avi_track_t *tk = p_sys->track[i_track];
1286
1287
                    /* add this chunk to the index */
1288
11.4k
                    avi_entry_t index;
1289
11.4k
                    index.i_flags  = AVI_GetKeyFlag(tk, avi_pk.i_peek);
1290
11.4k
                    index.i_pos    = avi_pk.i_pos;
1291
11.4k
                    index.i_length = avi_pk.i_size;
1292
11.4k
                    index.i_lengthtotal = index.i_length;
1293
11.4k
                    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
11.4k
                    if( i_indexid >= 0 &&
1297
11.4k
                        AVI_GetDPTS( tk, tk->demuxctx.i_toread ) > -p_sys->i_read_increment )
1298
9.74k
                    {
1299
9.74k
                        tk->i_idxposc = (unsigned int) i_indexid;
1300
9.74k
                        tk->i_idxposb = 0;
1301
9.74k
                        break;
1302
9.74k
                    }
1303
1.68k
                    else
1304
1.68k
                    {
1305
1.68k
                        if( AVI_PacketNext( p_demux ) )
1306
75
                        {
1307
75
                            msg_Warn( p_demux,
1308
75
                                      "cannot skip packet, track disabled" );
1309
75
                            return( AVI_TrackStopFinishedStreams( p_demux ) ? 0 : 1 );
1310
75
                        }
1311
1.68k
                    }
1312
11.4k
                }
1313
1.35M
            }
1314
1315
1.29M
        }
1316
18.3M
        else
1317
18.3M
        {
1318
18.3M
            if (vlc_stream_Seek(p_demux->s, i_pos))
1319
0
                return VLC_DEMUXER_EGENERIC;
1320
18.3M
        }
1321
1322
        /* Set the track to use */
1323
18.3M
        avi_track_t *tk = p_sys->track[i_track];
1324
1325
18.3M
        size_t i_size;
1326
18.3M
        unsigned i_ck_remaining_bytes = tk->idx.p_entry[tk->i_idxposc].i_length -
1327
18.3M
                                        tk->i_idxposb;
1328
1329
        /* read those data */
1330
18.3M
        if( tk->i_samplesize )
1331
9.13M
        {
1332
9.13M
            int64_t i_toread;
1333
1334
            /* remaining bytes to read inside the current read increment */
1335
9.13M
            if( ( i_toread = tk->demuxctx.i_toread ) <= 0 )
1336
613
            {
1337
613
                if( tk->i_samplesize > 1 )
1338
505
                {
1339
505
                    i_toread = tk->i_samplesize;
1340
505
                }
1341
108
                else
1342
108
                {
1343
                    /* refill current read increment */
1344
108
                    i_toread = AVI_PTSToByte( tk, VLC_TICK_FROM_MS(20) );
1345
108
                    i_toread = __MAX( i_toread, 100 );
1346
108
                }
1347
613
            }
1348
9.13M
            i_size = __MIN( i_ck_remaining_bytes, (size_t) i_toread );
1349
9.13M
        }
1350
9.24M
        else
1351
9.24M
        {
1352
9.24M
            assert(tk->i_idxposb == 0);
1353
9.24M
            i_size = i_ck_remaining_bytes;
1354
9.24M
        }
1355
1356
        /* need to read and skip tag/header */
1357
18.3M
        const uint8_t i_header = ( tk->i_idxposb == 0 ) ? 8 : 0;
1358
1359
18.3M
        if( ( p_frame = ReadFrame( p_demux, tk, i_header, i_size ) )==NULL )
1360
17.1M
        {
1361
17.1M
            msg_Warn( p_demux, "failed reading data" );
1362
17.1M
            tk->b_eof = false;
1363
17.1M
            tk->demuxctx.b_ok = false;
1364
17.1M
            continue;
1365
17.1M
        }
1366
1367
1.22M
        if( p_frame->i_pts == VLC_TICK_INVALID )
1368
1.22M
            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.22M
        if( tk->idx.p_entry[tk->i_idxposc].i_flags&AVIIF_KEYFRAME )
1373
1.20M
        {
1374
1.20M
            p_frame->i_flags = BLOCK_FLAG_TYPE_I;
1375
1.20M
        }
1376
14.4k
        else if( tk->fmt.i_cat == VIDEO_ES )
1377
1.16k
        {
1378
1.16k
            p_frame->i_flags = BLOCK_FLAG_TYPE_PB;
1379
1.16k
        }
1380
1381
        /* advance chunk/byte pointers */
1382
1.22M
        if( tk->i_samplesize )
1383
1.21M
        {
1384
1.21M
            tk->demuxctx.i_toread -= i_size;
1385
1.21M
            tk->i_idxposb += i_size;
1386
1.21M
            if( tk->i_idxposb >=
1387
1.21M
                    tk->idx.p_entry[tk->i_idxposc].i_length )
1388
2.36k
            {
1389
2.36k
                tk->i_idxposb = 0;
1390
2.36k
                tk->i_idxposc++;
1391
2.36k
            }
1392
1.21M
        }
1393
8.50k
        else /* full chunk */
1394
8.50k
        {
1395
            /* Goto to next chunk */
1396
8.50k
            tk->i_idxposc++;
1397
8.50k
            if( tk->fmt.i_cat == AUDIO_ES )
1398
1.28k
            {
1399
1.28k
                tk->i_blockno += tk->i_blocksize > 0 ? ( i_size + tk->i_blocksize - 1 ) / tk->i_blocksize : 1;
1400
1.28k
            }
1401
7.22k
            else if( tk->fmt.i_cat == SPU_ES )
1402
250
            {
1403
250
                tk->i_next_embedded_time = VLC_TICK_INVALID;
1404
250
            }
1405
8.50k
            tk->demuxctx.i_toread--;
1406
8.50k
        }
1407
1408
        /* check new chunk and set new read pos */
1409
1.22M
        if( tk->i_idxposc < tk->idx.i_size)
1410
1.21M
        {
1411
1.21M
            tk->demuxctx.i_posf =
1412
1.21M
                tk->idx.p_entry[tk->i_idxposc].i_pos;
1413
1.21M
            if( tk->i_idxposb > 0 )
1414
1.21M
            {
1415
1.21M
                tk->demuxctx.i_posf += 8 + tk->i_idxposb;
1416
1.21M
            }
1417
1418
1.21M
        }
1419
8.89k
        else /* all chunks read for this track */
1420
8.89k
        {
1421
8.89k
            tk->demuxctx.i_posf = -1;
1422
8.89k
        }
1423
1424
1.22M
        AVI_SendFrame( p_demux, tk, p_frame );
1425
1.22M
    }
1426
204M
}
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
744M
{
1871
    /* TODO: replace (and mp4) with better global helper (recursive checks) */
1872
744M
    if( i_timescale == i_newscale )
1873
2.46M
        return i_value;
1874
1875
741M
    if( (i_value >= 0 && i_value <= VLC_TICK_MAX / i_newscale) ||
1876
741M
        (i_value < 0  && i_value >= VLC_TICK_MIN / i_newscale) )
1877
625M
        return i_value * i_newscale / i_timescale;
1878
1879
    /* overflow */
1880
116M
    int64_t q = i_value / i_timescale;
1881
116M
    int64_t r = i_value % i_timescale;
1882
116M
    return q * i_newscale + r * i_newscale / i_timescale;
1883
741M
}
1884
1885
static int64_t AVI_PTSToChunk( avi_track_t *tk, vlc_tick_t i_pts )
1886
20.5M
{
1887
20.5M
    if( !tk->i_scale )
1888
0
        return 0;
1889
1890
20.5M
    i_pts = AVI_Rescale( i_pts, tk->i_scale, tk->i_rate );
1891
20.5M
    return SEC_FROM_VLC_TICK(i_pts);
1892
20.5M
}
1893
1894
static int64_t AVI_PTSToByte( avi_track_t *tk, vlc_tick_t i_pts )
1895
234M
{
1896
234M
    if( !tk->i_scale || !tk->i_samplesize )
1897
0
        return 0;
1898
1899
234M
    i_pts = AVI_Rescale( i_pts, tk->i_scale, tk->i_rate );
1900
234M
    return samples_from_vlc_tick( i_pts, tk->i_samplesize );
1901
234M
}
1902
1903
static vlc_tick_t AVI_GetDPTS( avi_track_t *tk, int64_t i_count )
1904
489M
{
1905
489M
    vlc_tick_t i_dpts = 0;
1906
1907
489M
    if( !tk->i_rate )
1908
27.7k
        return 0;
1909
1910
489M
    if( !tk->i_scale )
1911
9.50k
        return 0;
1912
1913
489M
    i_dpts = AVI_Rescale( CLOCK_FREQ * i_count, tk->i_rate, tk->i_scale );
1914
1915
489M
    if( tk->i_samplesize )
1916
438M
    {
1917
438M
        return i_dpts / tk->i_samplesize;
1918
438M
    }
1919
50.9M
    return i_dpts;
1920
489M
}
1921
1922
static vlc_tick_t AVI_GetPTS( avi_track_t *tk )
1923
256M
{
1924
    /* Lookup samples index */
1925
256M
    if( tk->i_samplesize && tk->idx.i_size )
1926
199M
    {
1927
199M
        int64_t i_count = 0;
1928
199M
        unsigned int idx = tk->i_idxposc;
1929
1930
        /* we need a valid entry we will emulate one */
1931
199M
        if( idx >= tk->idx.i_size )
1932
1.29M
        {
1933
            /* use the last entry */
1934
1.29M
            idx = tk->idx.i_size - 1;
1935
1.29M
            i_count = tk->idx.p_entry[idx].i_lengthtotal
1936
1.29M
                    + tk->idx.p_entry[idx].i_length;
1937
1.29M
        }
1938
198M
        else
1939
198M
        {
1940
198M
            i_count = tk->idx.p_entry[idx].i_lengthtotal;
1941
198M
        }
1942
199M
        return AVI_GetDPTS( tk, i_count + tk->i_idxposb );
1943
199M
    }
1944
1945
57.0M
    if( tk->fmt.i_cat == AUDIO_ES )
1946
55.4M
        return AVI_GetDPTS( tk, tk->i_blockno );
1947
1.60M
    else
1948
1.60M
        return AVI_GetDPTS( tk, tk->i_idxposc );
1949
57.0M
}
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
11.4k
{
2186
11.4k
    if( tk->is_qnap )
2187
634
    {
2188
634
        const uint8_t *p = p_byte;
2189
634
        if( IsQNAPCodec(VLC_FOURCC(p[0],p[1],p[2],p[3])) )
2190
4
            return p[4] & 0x01 ? AVIIF_KEYFRAME : 0;
2191
634
    }
2192
2193
11.4k
    switch( tk->fmt.i_codec )
2194
11.4k
    {
2195
242
        case VLC_CODEC_DIV1:
2196
            /* we have:
2197
             *  startcode:      0x00000100   32bits
2198
             *  framenumber     ?             5bits
2199
             *  piture type     0(I),1(P)     2bits
2200
             */
2201
242
            if( GetDWBE( p_byte ) != 0x00000100 )
2202
241
            {
2203
                /* it's not an msmpegv1 stream, strange...*/
2204
241
                return AVIIF_KEYFRAME;
2205
241
            }
2206
1
            return p_byte[4] & 0x06 ? 0 : AVIIF_KEYFRAME;
2207
2208
212
        case VLC_CODEC_DIV2:
2209
428
        case VLC_CODEC_DIV3:
2210
505
        case VLC_CODEC_WMV1:
2211
            /* we have
2212
             *  picture type    0(I),1(P)     2bits
2213
             */
2214
505
            return p_byte[0] & 0xC0 ? 0 : AVIIF_KEYFRAME;
2215
764
        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
764
            if( GetDWBE( p_byte ) != 0x000001b6 )
2221
762
            {
2222
                /* not true , need to find the first VOP header */
2223
762
                return AVIIF_KEYFRAME;
2224
762
            }
2225
2
            return p_byte[4] & 0xC0 ? 0 : AVIIF_KEYFRAME;
2226
2227
865
        case VLC_CODEC_H264:
2228
865
        {
2229
865
            uint32_t bytes = GetDWBE( p_byte );
2230
865
            enum h264_nal_unit_type_e i_nal_type;
2231
865
            if( bytes == 0x00000001 )
2232
345
                i_nal_type = h264_getNALType( &p_byte[4] );
2233
520
            else if( (bytes & 0xFFFFFF00) == 0x00000100 )
2234
9
                i_nal_type = h264_getNALType( &p_byte[3] );
2235
511
            else
2236
511
                return i_nal_type = 0;
2237
354
            return (i_nal_type == H264_NAL_SLICE_IDR) ? AVIIF_KEYFRAME : 0;
2238
865
        }
2239
2240
155
        case VLC_CODEC_HEVC:
2241
155
        {
2242
155
            uint32_t bytes = GetDWBE( p_byte );
2243
155
            uint8_t i_nal_type;
2244
155
            if( bytes == 0x00000001 )
2245
3
                i_nal_type = hevc_getNALType( &p_byte[4] );
2246
152
            else if( (bytes & 0xFFFFFF00) == 0x00000100 )
2247
5
                i_nal_type = hevc_getNALType( &p_byte[3] );
2248
147
            else
2249
147
                i_nal_type = 0;
2250
155
            return (i_nal_type >= HEVC_NAL_IDR_W_RADL &&
2251
155
                    i_nal_type <= HEVC_NAL_CRA) ? AVIIF_KEYFRAME : 0;
2252
865
        }
2253
2254
8.89k
        default:
2255
            /* I can't do it, so say yes */
2256
8.89k
            return AVIIF_KEYFRAME;
2257
11.4k
    }
2258
11.4k
}
2259
2260
vlc_fourcc_t AVI_FourccGetCodec( unsigned int i_cat, vlc_fourcc_t i_codec )
2261
9.13k
{
2262
9.13k
    switch( i_cat )
2263
9.13k
    {
2264
7.77k
        case AUDIO_ES:
2265
7.77k
            wf_tag_to_fourcc( i_codec, &i_codec, NULL );
2266
7.77k
            return i_codec;
2267
1.36k
        case VIDEO_ES:
2268
1.36k
            return vlc_fourcc_GetCodec( i_cat, i_codec );
2269
0
        default:
2270
0
            return VLC_CODEC_UNKNOWN;
2271
9.13k
    }
2272
9.13k
}
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
3.40M
{
2281
3.40M
    int c1, c2;
2282
2283
3.40M
    c1 = ((uint8_t *)&i_id)[0];
2284
3.40M
    c2 = ((uint8_t *)&i_id)[1];
2285
2286
3.40M
    if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )
2287
2.85M
    {
2288
2.85M
        *pi_number =  100; /* > max stream number */
2289
2.85M
        *pi_type = UNKNOWN_ES;
2290
2.85M
    }
2291
546k
    else
2292
546k
    {
2293
546k
        *pi_number = (c1 - '0') * 10 + (c2 - '0' );
2294
546k
        switch( VLC_TWOCC( ((uint8_t *)&i_id)[2], ((uint8_t *)&i_id)[3] ) )
2295
546k
        {
2296
20.5k
            case AVITWOCC_wb:
2297
20.5k
                *pi_type = AUDIO_ES;
2298
20.5k
                break;
2299
3.09k
            case AVITWOCC_dc:
2300
3.17k
            case AVITWOCC_db:
2301
3.18k
            case AVITWOCC_AC:
2302
3.18k
                *pi_type = VIDEO_ES;
2303
3.18k
                break;
2304
40
            case AVITWOCC_tx:
2305
112
            case AVITWOCC_sb:
2306
112
                *pi_type = SPU_ES;
2307
112
                break;
2308
29
            case AVITWOCC_pc:
2309
29
                *pi_type = IGNORE_ES;
2310
29
                break;
2311
522k
            default:
2312
522k
                *pi_type = UNKNOWN_ES;
2313
522k
                break;
2314
546k
        }
2315
546k
    }
2316
3.40M
}
2317
2318
/****************************************************************************
2319
 *
2320
 ****************************************************************************/
2321
static int AVI_PacketGetHeader( demux_t *p_demux, avi_packet_t *p_pk )
2322
17.5M
{
2323
17.5M
    const uint8_t *p_peek;
2324
2325
17.5M
    if( vlc_stream_Peek( p_demux->s, &p_peek, 16 ) < 16 )
2326
14.1M
    {
2327
14.1M
        return VLC_EGENERIC;
2328
14.1M
    }
2329
3.33M
    p_pk->i_fourcc  = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] );
2330
3.33M
    p_pk->i_size    = GetDWLE( p_peek + 4 );
2331
3.33M
    p_pk->i_pos     = vlc_stream_Tell( p_demux->s );
2332
3.33M
    if( p_pk->i_fourcc == AVIFOURCC_LIST || p_pk->i_fourcc == AVIFOURCC_RIFF )
2333
516k
    {
2334
516k
        p_pk->i_type = VLC_FOURCC( p_peek[8],  p_peek[9],
2335
516k
                                   p_peek[10], p_peek[11] );
2336
516k
    }
2337
2.82M
    else
2338
2.82M
    {
2339
2.82M
        p_pk->i_type = 0;
2340
2.82M
    }
2341
2342
3.33M
    memcpy( p_pk->i_peek, p_peek + 8, 8 );
2343
2344
3.33M
    AVI_ParseStreamHeader( p_pk->i_fourcc, &p_pk->i_stream, &p_pk->i_cat );
2345
3.33M
    return VLC_SUCCESS;
2346
17.5M
}
2347
2348
static int AVI_PacketNext( demux_t *p_demux )
2349
16.0M
{
2350
16.0M
    avi_packet_t    avi_ck;
2351
16.0M
    uint32_t        i_skip = 0;
2352
2353
16.0M
    if( AVI_PacketGetHeader( p_demux, &avi_ck ) )
2354
14.0M
    {
2355
14.0M
        return VLC_EGENERIC;
2356
14.0M
    }
2357
2358
1.98M
    if( avi_ck.i_fourcc == AVIFOURCC_LIST &&
2359
1.98M
        ( avi_ck.i_type == AVIFOURCC_rec || avi_ck.i_type == AVIFOURCC_movi ) )
2360
209k
    {
2361
209k
        i_skip = 12;
2362
209k
    }
2363
1.77M
    else if( avi_ck.i_fourcc == AVIFOURCC_RIFF &&
2364
1.77M
             avi_ck.i_type == AVIFOURCC_AVIX )
2365
10
    {
2366
10
        i_skip = 24;
2367
10
    }
2368
1.77M
    else
2369
1.77M
    {
2370
1.77M
        if( avi_ck.i_size > UINT32_MAX - 9 )
2371
2.14k
            return VLC_EGENERIC;
2372
1.77M
        i_skip = __EVEN( avi_ck.i_size ) + 8;
2373
1.77M
    }
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.98M
    if( vlc_stream_Read( p_demux->s, NULL, i_skip ) != i_skip )
2381
1.49M
    {
2382
1.49M
        return VLC_EGENERIC;
2383
1.49M
    }
2384
490k
    return VLC_SUCCESS;
2385
1.98M
}
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
31.2k
{
2424
31.2k
    p_index->i_size  = 0;
2425
31.2k
    p_index->i_max   = 0;
2426
31.2k
    p_index->p_entry = NULL;
2427
31.2k
}
2428
static void avi_index_Clean( avi_index_t *p_index )
2429
31.2k
{
2430
31.2k
    free( p_index->p_entry );
2431
31.2k
}
2432
105k
#define MAX_INDEX_ENTRIES __MIN(SIZE_MAX/sizeof(avi_entry_t), UINT32_MAX)
2433
7.10k
#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
102k
{
2437
    /* Update last chunk position */
2438
102k
    if( *pi_last_pos < p_entry->i_pos )
2439
13.1k
         *pi_last_pos = p_entry->i_pos;
2440
2441
102k
    if( p_index->i_size == MAX_INDEX_ENTRIES )
2442
0
        return -1;
2443
2444
    /* add the entry */
2445
102k
    if( p_index->i_size >= p_index->i_max )
2446
3.55k
    {
2447
3.55k
        if( MAX_INDEX_ENTRIES - INDEX_EXTENT > p_index->i_max )
2448
3.55k
            p_index->i_max += INDEX_EXTENT;
2449
0
        else
2450
0
            p_index->i_max = MAX_INDEX_ENTRIES;
2451
3.55k
        p_index->p_entry = realloc_or_free( p_index->p_entry,
2452
3.55k
                                            p_index->i_max * sizeof(avi_entry_t) );
2453
3.55k
        if( !p_index->p_entry )
2454
0
        {
2455
0
            avi_index_Init( p_index );
2456
0
            return -1;
2457
0
        }
2458
3.55k
    }
2459
    /* calculate cumulate length */
2460
102k
    if( p_index->i_size > 0 )
2461
98.5k
    {
2462
98.5k
        p_entry->i_lengthtotal =
2463
98.5k
            p_index->p_entry[p_index->i_size - 1].i_length +
2464
98.5k
                p_index->p_entry[p_index->i_size - 1].i_lengthtotal;
2465
98.5k
    }
2466
3.55k
    else
2467
3.55k
    {
2468
3.55k
        p_entry->i_lengthtotal = 0;
2469
3.55k
    }
2470
2471
102k
    p_index->p_entry[p_index->i_size++] = *p_entry;
2472
102k
    return p_index->i_size - 1;
2473
102k
}
2474
2475
static int AVI_IndexFind_idx1( demux_t *p_demux,
2476
                               avi_chunk_idx1_t **pp_idx1,
2477
                               uint64_t *pi_offset )
2478
10.3k
{
2479
10.3k
    demux_sys_t *p_sys = p_demux->p_sys;
2480
2481
10.3k
    avi_chunk_list_t *p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0, true);
2482
10.3k
    avi_chunk_idx1_t *p_idx1 = AVI_ChunkFind( p_riff, AVIFOURCC_idx1, 0, false);
2483
2484
10.3k
    if( !p_idx1 )
2485
9.35k
    {
2486
9.35k
        msg_Warn( p_demux, "cannot find idx1 chunk, no index defined" );
2487
9.35k
        return VLC_EGENERIC;
2488
9.35k
    }
2489
956
    *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
956
    avi_chunk_list_t *p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0, true );
2497
956
    if( !p_movi )
2498
3
        return VLC_EGENERIC;
2499
953
    uint64_t i_first_pos = UINT64_MAX;
2500
43.2k
    for( unsigned i = 0; i < __MIN( p_idx1->i_entry_count, 100 ); i++ )
2501
42.3k
    {
2502
42.3k
        if ( p_idx1->entry[i].i_length > 0 )
2503
33.3k
            i_first_pos = __MIN( i_first_pos, p_idx1->entry[i].i_pos );
2504
42.3k
    }
2505
2506
953
    const uint64_t i_movi_content = p_movi->i_chunk_pos + 8;
2507
953
    if( i_first_pos < i_movi_content )
2508
534
    {
2509
534
        *pi_offset = i_movi_content;
2510
534
    }
2511
419
    else if( p_sys->b_seekable && i_first_pos < UINT64_MAX )
2512
386
    {
2513
386
        const uint8_t *p_peek;
2514
386
        if( !vlc_stream_Seek( p_demux->s, i_movi_content + i_first_pos ) &&
2515
386
            vlc_stream_Peek( p_demux->s, &p_peek, 4 ) >= 4 &&
2516
386
            ( !isdigit( p_peek[0] ) || !isdigit( p_peek[1] ) ||
2517
63
              !isalpha( p_peek[2] ) || !isalpha( p_peek[3] ) ) )
2518
60
            *pi_offset = 0;
2519
326
        else
2520
326
            *pi_offset = i_movi_content;
2521
2522
386
        if( p_idx1->i_entry_count )
2523
386
        {
2524
            /* Invalidate offset if index refers past the data section to avoid false
2525
               positives when the offset equals sample size */
2526
386
            size_t i_dataend = *pi_offset + p_idx1->entry[p_idx1->i_entry_count - 1].i_pos +
2527
386
                                            p_idx1->entry[p_idx1->i_entry_count - 1].i_length;
2528
386
            if( i_dataend > p_movi->i_chunk_pos + p_movi->i_chunk_size )
2529
325
                *pi_offset = 0;
2530
386
        }
2531
386
    }
2532
33
    else
2533
33
    {
2534
33
        *pi_offset = 0;
2535
33
    }
2536
2537
953
    return VLC_SUCCESS;
2538
956
}
2539
2540
static int AVI_IndexLoad_idx1( demux_t *p_demux,
2541
                               avi_index_t p_index[], uint64_t *pi_last_offset )
2542
10.1k
{
2543
10.1k
    demux_sys_t *p_sys = p_demux->p_sys;
2544
2545
10.1k
    avi_chunk_idx1_t *p_idx1;
2546
10.1k
    uint64_t         i_offset;
2547
10.1k
    if( AVI_IndexFind_idx1( p_demux, &p_idx1, &i_offset ) )
2548
9.31k
        return VLC_EGENERIC;
2549
2550
814
    p_sys->b_indexloaded = true;
2551
2552
61.2k
    for( unsigned i_index = 0; i_index < p_idx1->i_entry_count; i_index++ )
2553
60.4k
    {
2554
60.4k
        enum es_format_category_e i_cat;
2555
60.4k
        unsigned i_stream;
2556
2557
60.4k
        AVI_ParseStreamHeader( p_idx1->entry[i_index].i_fourcc,
2558
60.4k
                               &i_stream,
2559
60.4k
                               &i_cat );
2560
60.4k
        if( i_stream < p_sys->i_track &&
2561
60.4k
            (i_cat == p_sys->track[i_stream]->fmt.i_cat || i_cat == UNKNOWN_ES ) )
2562
3.43k
        {
2563
3.43k
            avi_entry_t index;
2564
3.43k
            index.i_flags  = p_idx1->entry[i_index].i_flags&(~AVIIF_FIXKEYFRAME);
2565
3.43k
            index.i_pos    = p_idx1->entry[i_index].i_pos + i_offset;
2566
3.43k
            index.i_length = p_idx1->entry[i_index].i_length;
2567
3.43k
            index.i_lengthtotal = index.i_length;
2568
2569
3.43k
            avi_index_Append( &p_index[i_stream], pi_last_offset, &index );
2570
3.43k
        }
2571
60.4k
    }
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
814
    return VLC_SUCCESS;
2594
10.1k
}
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.34k
{
2599
1.34k
    demux_sys_t *p_sys = p_demux->p_sys;
2600
1.34k
    avi_entry_t index;
2601
2602
1.34k
    p_sys->b_indexloaded = true;
2603
2604
1.34k
    msg_Dbg( p_demux, "loading subindex(0x%x) %d entries", p_indx->i_indextype, p_indx->i_entriesinuse );
2605
1.34k
    if( p_indx->i_indexsubtype == 0 )
2606
765
    {
2607
73.3k
        for( unsigned i = 0; i < p_indx->i_entriesinuse; i++ )
2608
72.5k
        {
2609
72.5k
            index.i_flags  = p_indx->idx.std[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
2610
72.5k
            index.i_pos    = p_indx->i_baseoffset + p_indx->idx.std[i].i_offset - 8;
2611
72.5k
            index.i_length = p_indx->idx.std[i].i_size&0x7fffffff;
2612
72.5k
            index.i_lengthtotal = index.i_length;
2613
2614
72.5k
            avi_index_Append( p_index, pi_max_offset, &index );
2615
72.5k
        }
2616
765
    }
2617
581
    else if( p_indx->i_indexsubtype == AVI_INDEX_2FIELD )
2618
302
    {
2619
14.9k
        for( unsigned i = 0; i < p_indx->i_entriesinuse; i++ )
2620
14.6k
        {
2621
14.6k
            index.i_flags  = p_indx->idx.field[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;
2622
14.6k
            index.i_pos    = p_indx->i_baseoffset + p_indx->idx.field[i].i_offset - 8;
2623
14.6k
            index.i_length = p_indx->idx.field[i].i_size;
2624
14.6k
            index.i_lengthtotal = index.i_length;
2625
2626
14.6k
            avi_index_Append( p_index, pi_max_offset, &index );
2627
14.6k
        }
2628
302
    }
2629
279
    else
2630
279
    {
2631
279
        msg_Warn( p_demux, "unknown subtype index(0x%x)", p_indx->i_indexsubtype );
2632
279
    }
2633
1.34k
}
2634
2635
static void AVI_IndexLoad_indx( demux_t *p_demux,
2636
                                avi_index_t p_index[], uint64_t *pi_last_offset )
2637
10.1k
{
2638
10.1k
    demux_sys_t         *p_sys = p_demux->p_sys;
2639
2640
10.1k
    avi_chunk_list_t    *p_riff;
2641
10.1k
    avi_chunk_list_t    *p_hdrl;
2642
2643
10.1k
    p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0, true);
2644
10.1k
    p_hdrl = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0, true );
2645
2646
25.7k
    for( unsigned i_stream = 0; i_stream < p_sys->i_track; i_stream++ )
2647
15.6k
    {
2648
15.6k
        avi_chunk_list_t    *p_strl;
2649
15.6k
        avi_chunk_indx_t    *p_indx;
2650
2651
15.6k
        p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i_stream, true );
2652
15.6k
        p_indx = AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0, false );
2653
2654
15.6k
        if( !p_indx )
2655
14.7k
        {
2656
14.7k
            if( p_sys->b_odml )
2657
14.7k
                msg_Warn( p_demux, "cannot find indx (misdetect/broken OpenDML "
2658
14.7k
                                   "file?)" );
2659
14.7k
            continue;
2660
14.7k
        }
2661
2662
837
        if( p_indx->i_indextype == AVI_INDEX_OF_CHUNKS )
2663
220
        {
2664
220
            __Parse_indx( p_demux, &p_index[i_stream], pi_last_offset, p_indx );
2665
220
        }
2666
617
        else if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES )
2667
612
        {
2668
612
            if ( !p_sys->b_seekable )
2669
0
                return;
2670
612
            avi_chunk_t    ck_sub;
2671
22.1k
            for( unsigned i = 0; i < p_indx->i_entriesinuse; i++ )
2672
22.1k
            {
2673
22.1k
                if( vlc_stream_Seek( p_demux->s,
2674
22.1k
                                     p_indx->idx.super[i].i_offset ) ||
2675
22.1k
                    AVI_ChunkRead( p_demux->s, &ck_sub, NULL  ) )
2676
573
                {
2677
573
                    break;
2678
573
                }
2679
21.5k
                if( ck_sub.common.i_chunk_fourcc == AVIFOURCC_indx &&
2680
21.5k
                     ck_sub.indx.i_indextype == AVI_INDEX_OF_CHUNKS )
2681
1.12k
                    __Parse_indx( p_demux, &p_index[i_stream], pi_last_offset, &ck_sub.indx );
2682
21.5k
                AVI_ChunkClean( p_demux->s, &ck_sub );
2683
21.5k
            }
2684
612
        }
2685
5
        else
2686
5
        {
2687
5
            msg_Warn( p_demux, "unknown type index(0x%x)", p_indx->i_indextype );
2688
5
        }
2689
837
    }
2690
10.1k
}
2691
2692
static void AVI_IndexLoad( demux_t *p_demux )
2693
10.1k
{
2694
10.1k
    demux_sys_t *p_sys = p_demux->p_sys;
2695
2696
    /* Load indexes */
2697
10.1k
    assert( p_sys->i_track <= 100 );
2698
10.1k
    avi_index_t p_idx_indx[p_sys->i_track];
2699
10.1k
    avi_index_t p_idx_idx1[p_sys->i_track];
2700
25.7k
    for( unsigned i = 0; i < p_sys->i_track; i++ )
2701
15.6k
    {
2702
15.6k
        avi_index_Init( &p_idx_indx[i] );
2703
15.6k
        avi_index_Init( &p_idx_idx1[i] );
2704
15.6k
    }
2705
10.1k
    uint64_t i_indx_last_pos = p_sys->i_movi_lastchunk_pos;
2706
10.1k
    uint64_t i_idx1_last_pos = p_sys->i_movi_lastchunk_pos;
2707
2708
10.1k
    AVI_IndexLoad_indx( p_demux, p_idx_indx, &i_indx_last_pos );
2709
10.1k
    if( !p_sys->b_odml )
2710
10.1k
        AVI_IndexLoad_idx1( p_demux, p_idx_idx1, &i_idx1_last_pos );
2711
2712
    /* Select the longest index */
2713
25.7k
    for( unsigned i = 0; i < p_sys->i_track; i++ )
2714
15.6k
    {
2715
15.6k
        if( p_idx_indx[i].i_size > p_idx_idx1[i].i_size )
2716
243
        {
2717
243
            msg_Dbg( p_demux, "selected ODML index for stream[%u]", i );
2718
243
            free(p_sys->track[i]->idx.p_entry);
2719
243
            p_sys->track[i]->idx = p_idx_indx[i];
2720
243
            avi_index_Clean( &p_idx_idx1[i] );
2721
243
        }
2722
15.3k
        else
2723
15.3k
        {
2724
15.3k
            msg_Dbg( p_demux, "selected standard index for stream[%u]", i );
2725
15.3k
            free(p_sys->track[i]->idx.p_entry);
2726
15.3k
            p_sys->track[i]->idx = p_idx_idx1[i];
2727
15.3k
            avi_index_Clean( &p_idx_indx[i] );
2728
15.3k
        }
2729
15.6k
    }
2730
10.1k
    p_sys->i_movi_lastchunk_pos = __MAX( i_indx_last_pos, i_idx1_last_pos );
2731
2732
25.7k
    for( unsigned i = 0; i < p_sys->i_track; i++ )
2733
15.6k
    {
2734
15.6k
        avi_index_t *p_index = &p_sys->track[i]->idx;
2735
2736
        /* Fix key flag */
2737
15.6k
        bool b_key = false;
2738
17.0k
        for( unsigned j = 0; !b_key && j < p_index->i_size; j++ )
2739
1.40k
            b_key = p_index->p_entry[j].i_flags & AVIIF_KEYFRAME;
2740
15.6k
        if( !b_key )
2741
14.9k
        {
2742
14.9k
            msg_Warn( p_demux, "no key frame set for track %u", i );
2743
15.2k
            for( unsigned j = 0; j < p_index->i_size; j++ )
2744
368
                p_index->p_entry[j].i_flags |= AVIIF_KEYFRAME;
2745
14.9k
        }
2746
2747
        /* */
2748
15.6k
        msg_Dbg( p_demux, "stream[%d] created %d index entries",
2749
15.6k
                 i, p_index->i_size );
2750
15.6k
    }
2751
10.1k
}
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
10.4k
{
2887
10.4k
    demux_sys_t *p_sys = p_demux->p_sys;
2888
2889
10.4k
    vlc_meta_t *p_meta = p_sys->meta = vlc_meta_New();
2890
10.4k
    if( !p_meta )
2891
0
        return;
2892
2893
10.4k
    char buffer[200];
2894
10.4k
    snprintf( buffer, sizeof(buffer), "%s%s%s%s",
2895
10.4k
              p_avih->i_flags&AVIF_HASINDEX      ? " HAS_INDEX"      : "",
2896
10.4k
              p_avih->i_flags&AVIF_MUSTUSEINDEX  ? " MUST_USE_INDEX" : "",
2897
10.4k
              p_avih->i_flags&AVIF_ISINTERLEAVED ? " IS_INTERLEAVED" : "",
2898
10.4k
              p_avih->i_flags&AVIF_TRUSTCKTYPE   ? " TRUST_CKTYPE"   : "" );
2899
10.4k
    vlc_meta_SetSetting( p_meta, buffer );
2900
2901
10.4k
    avi_chunk_list_t *p_info = AVI_ChunkFind( p_riff, AVIFOURCC_INFO, 0, true );
2902
10.4k
    if( !p_info )
2903
9.25k
        return;
2904
2905
1.17k
    static const struct {
2906
1.17k
        vlc_fourcc_t i_id;
2907
1.17k
        int          i_type;
2908
1.17k
    } p_dsc[] = {
2909
1.17k
        { AVIFOURCC_IART, vlc_meta_Artist },
2910
1.17k
        { AVIFOURCC_ICMT, vlc_meta_Description },
2911
1.17k
        { AVIFOURCC_ICOP, vlc_meta_Copyright },
2912
1.17k
        { AVIFOURCC_IGNR, vlc_meta_Genre },
2913
1.17k
        { AVIFOURCC_INAM, vlc_meta_Title },
2914
1.17k
        { AVIFOURCC_ICRD, vlc_meta_Date },
2915
1.17k
        { AVIFOURCC_ILNG, vlc_meta_Language },
2916
1.17k
        { AVIFOURCC_IRTD, vlc_meta_Rating },
2917
1.17k
        { AVIFOURCC_IWEB, vlc_meta_URL },
2918
1.17k
        { AVIFOURCC_IPRT, vlc_meta_TrackNumber },
2919
1.17k
        { AVIFOURCC_IFRM, vlc_meta_TrackTotal },
2920
1.17k
        { 0, -1 }
2921
1.17k
    };
2922
14.0k
    for( int i = 0; p_dsc[i].i_id != 0; i++ )
2923
12.8k
    {
2924
12.8k
        avi_chunk_STRING_t *p_strz = AVI_ChunkFind( p_info, p_dsc[i].i_id, 0, false );
2925
12.8k
        if( !p_strz || !p_strz->p_str )
2926
12.8k
            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.17k
    static const vlc_fourcc_t p_extra[] = {
2937
1.17k
        AVIFOURCC_IARL, AVIFOURCC_ICMS, AVIFOURCC_ICRP, AVIFOURCC_IDIM, AVIFOURCC_IDPI,
2938
1.17k
        AVIFOURCC_IENG, AVIFOURCC_IKEY, AVIFOURCC_ILGT, AVIFOURCC_IMED, AVIFOURCC_IPLT,
2939
1.17k
        AVIFOURCC_IPRD, AVIFOURCC_ISBJ, AVIFOURCC_ISFT, AVIFOURCC_ISHP, AVIFOURCC_ISRC,
2940
1.17k
        AVIFOURCC_ISRF, AVIFOURCC_ITCH, AVIFOURCC_ISMP, AVIFOURCC_IDIT, AVIFOURCC_ISGN,
2941
1.17k
        AVIFOURCC_IWRI, AVIFOURCC_IPRO, AVIFOURCC_ICNM, AVIFOURCC_IPDS, AVIFOURCC_IEDT,
2942
1.17k
        AVIFOURCC_ICDS, AVIFOURCC_IMUS, AVIFOURCC_ISTD, AVIFOURCC_IDST, AVIFOURCC_ICNT,
2943
1.17k
        AVIFOURCC_ISTR, 0,
2944
1.17k
    };
2945
2946
37.5k
    for( int i = 0; p_extra[i] != 0; i++ )
2947
36.3k
    {
2948
36.3k
        avi_chunk_STRING_t *p_strz = AVI_ChunkFind( p_info, p_extra[i], 0, false );
2949
36.3k
        if( !p_strz || !p_strz->p_str )
2950
35.3k
            continue;
2951
933
        char *psz_value = FromACP( p_strz->p_str );
2952
933
        if( !psz_value )
2953
23
            continue;
2954
2955
910
        if( *psz_value )
2956
902
            vlc_meta_SetExtra( p_meta, p_strz->p_type, psz_value );
2957
910
        free( psz_value );
2958
910
    }
2959
1.17k
}
2960
2961
static void AVI_DvHandleAudio( demux_t *p_demux, avi_track_t *tk, block_t *p_frame )
2962
193
{
2963
193
    size_t i_offset = 80 * 6 + 80 * 16 * 3 + 3;
2964
193
    if( p_frame->i_buffer < i_offset + 5 )
2965
94
        return;
2966
2967
99
    if( p_frame->p_buffer[i_offset] != 0x50 )
2968
16
        return;
2969
2970
83
    es_format_t fmt;
2971
83
    dv_get_audio_format( &fmt, &p_frame->p_buffer[i_offset + 1] );
2972
2973
83
    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
83
    if( !tk->p_es_dv_audio )
2980
80
    {
2981
80
        tk->p_es_dv_audio = es_out_Add( p_demux->out, &fmt );
2982
80
        tk->i_dv_audio_rate = fmt.audio.i_rate;
2983
80
    }
2984
2985
83
    es_format_Clean( &fmt );
2986
2987
83
    block_t *p_frame_audio = dv_extract_audio( p_frame );
2988
83
    if( p_frame_audio )
2989
71
    {
2990
71
        if( tk->p_es_dv_audio )
2991
71
            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
71
    }
2995
83
}
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
188
{
3021
188
    demux_sys_t *p_sys = p_demux->p_sys;
3022
188
    block_t *p_block = NULL;
3023
188
    input_attachment_t *p_attachment = NULL;
3024
188
    char *psz_description = NULL;
3025
188
    avi_chunk_indx_t *p_indx = NULL;
3026
3027
188
    if( !p_sys->b_seekable )
3028
0
        goto exit;
3029
3030
188
    p_indx = AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0, false );
3031
188
    avi_chunk_t ck;
3032
188
    int64_t  i_position;
3033
188
    unsigned i_size;
3034
188
    if( p_indx )
3035
14
    {
3036
14
        if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES &&
3037
14
            p_indx->i_entriesinuse > 0 )
3038
4
        {
3039
4
            if( vlc_stream_Seek( p_demux->s, p_indx->idx.super[0].i_offset ) ||
3040
4
                AVI_ChunkRead( p_demux->s, &ck, NULL  ) ||
3041
4
                ck.common.i_chunk_fourcc != AVIFOURCC_indx )
3042
3
                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
174
    else
3056
174
    {
3057
174
        avi_chunk_idx1_t *p_idx1;
3058
174
        uint64_t         i_offset;
3059
3060
174
        if( AVI_IndexFind_idx1( p_demux, &p_idx1, &i_offset ) )
3061
35
            goto exit;
3062
3063
139
        i_size = 0;
3064
9.15k
        for( unsigned i = 0; i < p_idx1->i_entry_count; i++ )
3065
9.02k
        {
3066
9.02k
            const idx1_entry_t *e = &p_idx1->entry[i];
3067
9.02k
            enum es_format_category_e i_cat;
3068
9.02k
            unsigned i_stream_idx;
3069
3070
9.02k
            AVI_ParseStreamHeader( e->i_fourcc, &i_stream_idx, &i_cat );
3071
9.02k
            if( i_cat == SPU_ES && i_stream_idx == i_stream )
3072
11
            {
3073
11
                i_position = e->i_pos + i_offset;
3074
11
                i_size     = e->i_length + 8;
3075
11
                break;
3076
11
            }
3077
9.02k
        }
3078
139
        if( i_size <= 0 )
3079
128
            goto exit;
3080
139
    }
3081
3082
    /* */
3083
14
    if( i_size > 10000000 )
3084
5
    {
3085
5
        msg_Dbg( p_demux, "Attached subtitle too big: %u", i_size );
3086
5
        goto exit;
3087
5
    }
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
188
exit:
3135
188
    free( psz_description );
3136
3137
188
    if( p_block )
3138
5
        block_Release( p_block );
3139
3140
188
    if( p_attachment )
3141
188
        msg_Dbg( p_demux, "Loaded an embedded subtitle" );
3142
188
    else
3143
188
        msg_Warn( p_demux, "Failed to load an embedded subtitle" );
3144
3145
188
    if( p_indx == &ck.indx )
3146
1
        AVI_ChunkClean( p_demux->s, &ck );
3147
188
}
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
15.6M
{
3203
15.6M
    demux_sys_t *p_sys = p_demux->p_sys;
3204
15.6M
    unsigned int i;
3205
15.6M
    int b_end = true;
3206
3207
44.3M
    for( i = 0; i < p_sys->i_track; i++ )
3208
28.6M
    {
3209
28.6M
        avi_track_t *tk = p_sys->track[i];
3210
28.6M
        if( tk->i_idxposc >= tk->idx.i_size )
3211
10.2M
        {
3212
10.2M
            tk->b_eof = true;
3213
10.2M
        }
3214
18.3M
        else
3215
18.3M
        {
3216
18.3M
            b_end = false;
3217
18.3M
        }
3218
28.6M
    }
3219
15.6M
    return( b_end );
3220
15.6M
}
3221
3222
/****************************************************************************
3223
 * AVI_MovieGetLength give max streams length in ticks
3224
 ****************************************************************************/
3225
static vlc_tick_t  AVI_MovieGetLength( demux_t *p_demux )
3226
10.1k
{
3227
10.1k
    demux_sys_t  *p_sys = p_demux->p_sys;
3228
10.1k
    vlc_tick_t   i_maxlength = 0;
3229
10.1k
    unsigned int i;
3230
3231
25.7k
    for( i = 0; i < p_sys->i_track; i++ )
3232
15.6k
    {
3233
15.6k
        avi_track_t *tk = p_sys->track[i];
3234
15.6k
        vlc_tick_t i_length;
3235
3236
        /* fix length for each stream */
3237
15.6k
        if( tk->idx.i_size < 1 || !tk->idx.p_entry )
3238
14.7k
        {
3239
14.7k
            continue;
3240
14.7k
        }
3241
3242
899
        if( tk->i_samplesize )
3243
625
        {
3244
625
            i_length = AVI_GetDPTS( tk,
3245
625
                                    tk->idx.p_entry[tk->idx.i_size-1].i_lengthtotal +
3246
625
                                        tk->idx.p_entry[tk->idx.i_size-1].i_length );
3247
625
        }
3248
274
        else
3249
274
        {
3250
274
            i_length = AVI_GetDPTS( tk, tk->idx.i_size );
3251
274
        }
3252
3253
899
        msg_Dbg( p_demux,
3254
899
                 "stream[%d] length:%"PRId64" (based on index)",
3255
899
                 i,
3256
899
                 SEC_FROM_VLC_TICK(i_length) );
3257
899
        i_maxlength = __MAX( i_maxlength, i_length );
3258
899
    }
3259
3260
10.1k
    return i_maxlength;
3261
10.1k
}