Coverage Report

Created: 2026-09-28 07:27

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