Coverage Report

Created: 2026-01-10 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/demux/mpeg/ps.c
Line
Count
Source
1
/*****************************************************************************
2
 * ps.c: Program Stream demux module for VLC.
3
 *****************************************************************************
4
 * Copyright (C) 2004-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
31
#include <vlc_common.h>
32
#include <vlc_plugin.h>
33
#include <vlc_demux.h>
34
35
#include "pes.h"
36
#include "ps.h"
37
38
/* TODO:
39
 *  - re-add pre-scanning.
40
 *  - ...
41
 */
42
43
#define TIME_TEXT N_("Trust MPEG timestamps")
44
#define TIME_LONGTEXT N_("Normally we use the timestamps of the MPEG files " \
45
    "to calculate position and duration. However sometimes this might not " \
46
    "be usable. Disable this option to calculate from the bitrate instead." )
47
48
885
#define PS_PACKET_PROBE 3
49
1
#define CDXA_HEADER_SIZE 44
50
0
#define CDXA_SECTOR_SIZE 2352
51
0
#define CDXA_SECTOR_HEADER_SIZE 24
52
53
/*****************************************************************************
54
 * Module descriptor
55
 *****************************************************************************/
56
static int  OpenForce( vlc_object_t * );
57
static int  Open   ( vlc_object_t * );
58
static void Close  ( vlc_object_t * );
59
60
108
vlc_module_begin ()
61
54
    set_description( N_("MPEG-PS demuxer") )
62
54
    set_shortname( N_("PS") )
63
54
    set_subcategory( SUBCAT_INPUT_DEMUX )
64
54
    set_capability( "demux", 1 )
65
108
    set_callbacks( OpenForce, Close )
66
54
    add_shortcut( "ps" )
67
68
54
    add_bool( "ps-trust-timestamps", true, TIME_TEXT,
69
54
                 TIME_LONGTEXT )
70
54
        change_safe ()
71
72
54
    add_submodule ()
73
54
    set_description( N_("MPEG-PS demuxer") )
74
54
    set_capability( "demux", 9 )
75
108
    set_callbacks( Open, Close )
76
54
    add_shortcut( "ps" )
77
54
vlc_module_end ()
78
79
/*****************************************************************************
80
 * Local prototypes
81
 *****************************************************************************/
82
83
typedef struct
84
{
85
    ps_psm_t    psm;
86
    ps_track_t  tk[PS_TK_COUNT];
87
88
    vlc_tick_t  i_pack_scr; /* current read pack scr value, temp */
89
    vlc_tick_t  i_first_scr; /* media offset */
90
    vlc_tick_t  i_scr; /* committed, current position */
91
    int64_t     i_scr_track_id;
92
    int         i_mux_rate;
93
    vlc_tick_t  i_length;
94
    int         i_time_track_index;
95
    vlc_tick_t  i_current_pts;
96
    uint64_t    i_start_byte;
97
    uint64_t    i_lastpack_byte;
98
99
    int         i_aob_mlp_count;
100
101
    bool  b_lost_sync;
102
    bool  b_have_pack;
103
    bool  b_bad_scr;
104
    bool  b_seekable;
105
    enum
106
    {
107
        MPEG_PS = 0,
108
        CDXA_PS,
109
        PSMF_PS,
110
        IMKH_PS,
111
    } format;
112
    enum ps_source source;
113
114
    int         current_title;
115
    int         current_seekpoint;
116
    unsigned    updates;
117
} demux_sys_t;
118
119
static int Demux  ( demux_t *p_demux );
120
static int Control( demux_t *p_demux, int i_query, va_list args );
121
122
static int      ps_pkt_resynch( stream_t *, int, bool );
123
static block_t *ps_pkt_read   ( stream_t * );
124
125
static void CreateOrUpdateES( demux_t*p_demux )
126
17.4k
{
127
17.4k
    demux_sys_t *p_sys = p_demux->p_sys;
128
129
10.1M
    for( int i = 0; i < PS_TK_COUNT; i++ )
130
10.1M
    {
131
10.1M
        ps_track_t *tk = &p_sys->tk[i];
132
10.1M
        if( !tk->b_updated )
133
10.1M
            continue;
134
135
18.0k
        if( tk->es )
136
16.0k
            es_out_Del( p_demux->out, tk->es );
137
138
18.0k
        if( tk->fmt.i_cat != UNKNOWN_ES )
139
18.0k
            tk->es = es_out_Add( p_demux->out, &tk->fmt );
140
18.0k
        tk->b_updated = false;
141
18.0k
    }
142
17.4k
}
143
144
/*****************************************************************************
145
 * Open
146
 *****************************************************************************/
147
static int OpenCommon( vlc_object_t *p_this, bool b_force )
148
885
{
149
885
    demux_t     *p_demux = (demux_t*)p_this;
150
885
    demux_sys_t *p_sys;
151
152
885
    const uint8_t *p_peek;
153
885
    ssize_t i_peek = 0;
154
885
    ssize_t i_offset = 0;
155
885
    int i_skip = 0;
156
885
    unsigned i_max_packets = PS_PACKET_PROBE;
157
885
    int format = MPEG_PS;
158
885
    int i_mux_rate = 0;
159
885
    vlc_tick_t i_length = VLC_TICK_INVALID;
160
161
885
    i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 16 );
162
885
    if( i_peek < 16 )
163
0
        return VLC_EGENERIC;
164
165
885
    if( !memcmp( p_peek, "PSMF", 4 ) &&
166
0
        (GetDWBE( &p_peek[4] ) & 0x30303030) == 0x30303030 )
167
0
    {
168
0
        i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 100 );
169
0
        if( i_peek < 100 )
170
0
            return VLC_EGENERIC;
171
0
        i_skip = i_offset = GetWBE( &p_peek[10] );
172
0
        format = PSMF_PS;
173
0
        msg_Info( p_demux, "Detected PSMF-PS header");
174
0
        i_mux_rate = GetDWBE( &p_peek[96] );
175
0
        if( GetDWBE( &p_peek[86] ) > 0 )
176
0
            i_length = vlc_tick_from_samples( GetDWBE( &p_peek[92] ), GetDWBE( &p_peek[86] ));
177
0
    }
178
885
    else if( !memcmp( p_peek, "IMKH", 4 ) )
179
9
    {
180
9
        msg_Info( p_demux, "Detected Hikvision PVA header");
181
9
        i_skip = 40;
182
9
        format = IMKH_PS;
183
9
        i_max_packets = 0;
184
9
    }
185
876
    else if( !memcmp( p_peek, "RIFF", 4 ) && !memcmp( &p_peek[8], "CDXA", 4 ) )
186
1
    {
187
1
        format = CDXA_PS;
188
1
        i_max_packets = 0; /* We can't probe here */
189
1
        i_skip = CDXA_HEADER_SIZE;
190
1
        msg_Info( p_demux, "Detected CDXA-PS" );
191
        /* FIXME: have a proper way to decap CD sectors or make an access stream filter */
192
1
    }
193
875
    else if( b_force )
194
429
    {
195
429
        msg_Warn( p_demux, "this does not look like an MPEG PS stream, "
196
429
                  "continuing anyway" );
197
429
        i_max_packets = 0;
198
429
    }
199
200
886
    for( unsigned i=0; i<i_max_packets; i++ )
201
447
    {
202
447
        if( i_peek < i_offset + 16 )
203
1
        {
204
1
            i_peek = vlc_stream_Peek( p_demux->s, &p_peek, i_offset + 16 );
205
1
            if( i_peek < i_offset + 16 )
206
1
                return VLC_EGENERIC;
207
1
        }
208
209
446
        const uint8_t startcode[3] = { 0x00, 0x00, 0x01 };
210
446
        const uint8_t *p_header = &p_peek[i_offset];
211
446
        if( memcmp( p_header, startcode, 3 ) ||
212
4
           ( (p_header[3] & 0xB0) != 0xB0 &&
213
2
            !(p_header[3] >= 0xC0 && p_header[3] <= 0xEF) &&
214
2
              p_header[3] != STREAM_ID_EXTENDED_STREAM_ID &&
215
2
              p_header[3] != STREAM_ID_PROGRAM_STREAM_DIRECTORY ) )
216
444
            return VLC_EGENERIC;
217
218
2
        ssize_t i_pessize = ps_pkt_size( p_header, 16 );
219
2
        if( i_pessize < 5 )
220
1
            return VLC_EGENERIC;
221
1
        i_offset += i_pessize;
222
1
    }
223
224
439
    if( i_skip && !p_demux->b_preparsing &&
225
10
        vlc_stream_Read( p_demux->s, NULL, i_skip ) != i_skip )
226
0
        return VLC_EGENERIC;
227
228
    /* Fill p_demux field */
229
439
    p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
230
439
    if( !p_sys ) return VLC_ENOMEM;
231
232
439
    p_demux->pf_demux = Demux;
233
439
    p_demux->pf_control = Control;
234
235
    /* Init p_sys */
236
439
    p_sys->i_mux_rate = i_mux_rate;
237
439
    p_sys->i_pack_scr  = VLC_TICK_INVALID;
238
439
    p_sys->i_first_scr = VLC_TICK_INVALID;
239
439
    p_sys->i_scr = VLC_TICK_INVALID;
240
439
    p_sys->i_scr_track_id = 0;
241
439
    p_sys->i_length   = i_length;
242
439
    p_sys->i_current_pts = VLC_TICK_INVALID;
243
439
    p_sys->i_time_track_index = -1;
244
439
    p_sys->i_aob_mlp_count = 0;
245
439
    p_sys->i_start_byte = i_skip;
246
439
    p_sys->i_lastpack_byte = i_skip;
247
248
439
    p_sys->b_lost_sync = false;
249
439
    p_sys->b_have_pack = false;
250
439
    p_sys->b_bad_scr   = false;
251
439
    p_sys->b_seekable  = false;
252
439
    p_sys->format      = format;
253
439
    p_sys->current_title = 0;
254
439
    p_sys->current_seekpoint = 0;
255
439
    p_sys->updates = 0;
256
257
439
    p_sys->source = PS_SOURCE_UNKNOWN;
258
439
    if ( likely(p_demux->s->psz_url != NULL) )
259
0
    {
260
0
        size_t url_len = strlen( p_demux->s->psz_url );
261
0
        if ( url_len >= 4 )
262
0
        {
263
0
            if ( !strncasecmp( &p_demux->s->psz_url[url_len-4], ".AOB", 4 ))
264
0
                p_sys->source = PS_SOURCE_AOB;
265
0
            if ( !strncasecmp( &p_demux->s->psz_url[url_len-4], ".VOB", 4 ))
266
0
                p_sys->source = PS_SOURCE_VOB;
267
0
        }
268
0
    }
269
270
439
    vlc_stream_Control( p_demux->s, STREAM_CAN_SEEK, &p_sys->b_seekable );
271
272
439
    ps_psm_init( &p_sys->psm );
273
439
    ps_track_init( p_sys->tk );
274
275
    /* TODO prescanning of ES */
276
277
439
    return VLC_SUCCESS;
278
439
}
279
280
static int OpenForce( vlc_object_t *p_this )
281
429
{
282
429
    return OpenCommon( p_this, true );
283
429
}
284
285
static int Open( vlc_object_t *p_this )
286
456
{
287
456
    return OpenCommon( p_this, p_this->force );
288
456
}
289
290
/*****************************************************************************
291
 * Close
292
 *****************************************************************************/
293
static void Close( vlc_object_t *p_this )
294
439
{
295
439
    demux_t     *p_demux = (demux_t*)p_this;
296
439
    demux_sys_t *p_sys = p_demux->p_sys;
297
439
    int i;
298
299
256k
    for( i = 0; i < PS_TK_COUNT; i++ )
300
256k
    {
301
256k
        ps_track_t *tk = &p_sys->tk[i];
302
256k
        es_format_Clean( &tk->fmt );
303
256k
        if( tk->b_configured && tk->es != NULL )
304
1.97k
            es_out_Del( p_demux->out, tk->es );
305
256k
    }
306
307
439
    ps_psm_destroy( &p_sys->psm );
308
309
439
    free( p_sys );
310
439
}
311
312
static int Probe( demux_t *p_demux, bool b_end )
313
99.4k
{
314
99.4k
    demux_sys_t *p_sys = p_demux->p_sys;
315
99.4k
    int i_ret, i_id;
316
99.4k
    block_t *p_pkt;
317
318
99.4k
    i_ret = ps_pkt_resynch( p_demux->s, p_sys->format, p_sys->b_have_pack );
319
99.4k
    if( i_ret < 0 )
320
240
    {
321
240
        return VLC_DEMUXER_EOF;
322
240
    }
323
99.2k
    else if( i_ret == 0 )
324
12.4k
    {
325
12.4k
        if( !p_sys->b_lost_sync )
326
12.4k
            msg_Warn( p_demux, "garbage at input, trying to resync..." );
327
328
12.4k
        p_sys->b_lost_sync = true;
329
12.4k
        return VLC_DEMUXER_SUCCESS;
330
12.4k
    }
331
332
86.7k
    if( p_sys->b_lost_sync ) msg_Warn( p_demux, "found sync code" );
333
86.7k
    p_sys->b_lost_sync = false;
334
335
86.7k
    if( ( p_pkt = ps_pkt_read( p_demux->s ) ) == NULL )
336
101
    {
337
101
        return VLC_DEMUXER_EOF;
338
101
    }
339
340
86.6k
    i_id = ps_pkt_id( p_pkt->p_buffer, p_pkt->i_buffer, p_sys->source );
341
86.6k
    if( i_id >= 0xc0 )
342
63.4k
    {
343
63.4k
        ps_track_t *tk = &p_sys->tk[ps_id_to_tk(i_id)];
344
63.4k
        if( !ps_pkt_parse_pes( VLC_OBJECT(p_demux), p_pkt, tk->i_skip ) &&
345
40.5k
             p_pkt->i_pts != VLC_TICK_INVALID )
346
17.5k
        {
347
17.5k
            if( b_end && (tk->i_last_pts == VLC_TICK_INVALID || p_pkt->i_pts > tk->i_last_pts) )
348
797
            {
349
797
                tk->i_last_pts = p_pkt->i_pts;
350
797
            }
351
16.7k
            else if ( tk->i_first_pts == VLC_TICK_INVALID )
352
653
            {
353
653
                tk->i_first_pts = p_pkt->i_pts;
354
653
            }
355
17.5k
        }
356
63.4k
    }
357
23.2k
    else if( i_id == PS_STREAM_ID_PACK_HEADER )
358
565
    {
359
565
        vlc_tick_t i_scr; int dummy;
360
565
        if( !b_end && !ps_pkt_parse_pack( p_pkt->p_buffer, p_pkt->i_buffer,
361
127
                                          &i_scr, &dummy ) )
362
108
        {
363
108
            if( p_sys->i_first_scr == VLC_TICK_INVALID )
364
15
                p_sys->i_first_scr = i_scr;
365
108
        }
366
565
        p_sys->b_have_pack = true;
367
565
    }
368
369
86.6k
    block_Release( p_pkt );
370
86.6k
    return VLC_DEMUXER_SUCCESS;
371
86.7k
}
372
373
static bool FindLength( demux_t *p_demux )
374
391
{
375
391
    demux_sys_t *p_sys = p_demux->p_sys;
376
377
391
    if( !var_CreateGetBool( p_demux, "ps-trust-timestamps" ) )
378
0
        return true;
379
380
391
    if( p_sys->i_length == VLC_TICK_INVALID ) /* First time */
381
391
    {
382
391
        p_sys->i_length = VLC_TICK_0;
383
        /* Check beginning */
384
391
        int i = 0;
385
391
        uint64_t i_current_pos = vlc_stream_Tell( p_demux->s );
386
14.1k
        while( i < 40 && Probe( p_demux, false ) > 0 ) i++;
387
388
        /* Check end */
389
391
        uint64_t i_size;
390
391
        if( vlc_stream_GetSize( p_demux->s, &i_size ) != VLC_SUCCESS )
391
0
          return false;
392
391
        uint64_t i_end = VLC_CLIP( i_size, 0, 200000 );
393
391
        if( vlc_stream_Seek( p_demux->s, i_size - i_end ) == VLC_SUCCESS )
394
391
        {
395
391
            i = 0;
396
85.7k
            while( i < 400 && Probe( p_demux, true ) > 0 ) i++;
397
391
            if( vlc_stream_Seek( p_demux->s, i_current_pos ) != VLC_SUCCESS )
398
0
                    return false;
399
391
        }
400
0
        else return false;
401
391
    }
402
403
    /* Find the longest track */
404
228k
    for( int i = 0; i < PS_TK_COUNT; i++ )
405
228k
    {
406
228k
        ps_track_t *tk = &p_sys->tk[i];
407
228k
        if( tk->i_first_pts != VLC_TICK_INVALID &&
408
653
            tk->i_last_pts > tk->i_first_pts )
409
84
        {
410
84
            vlc_tick_t i_length = tk->i_last_pts - tk->i_first_pts;
411
84
            if( i_length > p_sys->i_length )
412
80
            {
413
80
                p_sys->i_length = i_length;
414
80
                p_sys->i_time_track_index = i;
415
80
                msg_Dbg( p_demux, "we found a length of: %"PRId64 "s", SEC_FROM_VLC_TICK(p_sys->i_length) );
416
80
            }
417
84
        }
418
228k
    }
419
391
    return true;
420
391
}
421
422
static void NotifyDiscontinuity( ps_track_t *p_tk, es_out_t *out )
423
3.75k
{
424
3.75k
    bool b_selected;
425
2.19M
    for( size_t i = 0; i < PS_TK_COUNT; i++ )
426
2.19M
    {
427
2.19M
        ps_track_t *tk = &p_tk[i];
428
2.19M
        if( tk->es &&
429
24.3k
                es_out_Control( out, ES_OUT_GET_ES_STATE, tk->es, &b_selected ) == VLC_SUCCESS
430
24.3k
                && b_selected )
431
24.3k
        {
432
24.3k
            tk->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY;
433
24.3k
        }
434
2.19M
    }
435
3.75k
}
436
437
static void CheckPCR( demux_sys_t *p_sys, es_out_t *out, vlc_tick_t i_scr )
438
4.62k
{
439
4.62k
    if( p_sys->i_scr != VLC_TICK_INVALID &&
440
4.48k
        llabs( p_sys->i_scr - i_scr ) > VLC_TICK_FROM_SEC(1) )
441
875
        NotifyDiscontinuity( p_sys->tk, out );
442
4.62k
}
443
444
/*****************************************************************************
445
 * Demux:
446
 *****************************************************************************/
447
static int Demux( demux_t *p_demux )
448
207k
{
449
207k
    demux_sys_t *p_sys = p_demux->p_sys;
450
207k
    int i_ret, i_mux_rate;
451
207k
    block_t *p_pkt;
452
453
207k
    i_ret = ps_pkt_resynch( p_demux->s, p_sys->format, p_sys->b_have_pack );
454
207k
    if( i_ret < 0 )
455
306
    {
456
306
        return VLC_DEMUXER_EOF;
457
306
    }
458
206k
    else if( i_ret == 0 )
459
22.2k
    {
460
22.2k
        if( !p_sys->b_lost_sync )
461
2.87k
        {
462
2.87k
            msg_Warn( p_demux, "garbage at input from %"PRIu64", trying to resync...",
463
2.87k
                                vlc_stream_Tell(p_demux->s) );
464
2.87k
            NotifyDiscontinuity( p_sys->tk, p_demux->out );
465
2.87k
        }
466
467
22.2k
        p_sys->b_lost_sync = true;
468
22.2k
        return VLC_DEMUXER_SUCCESS;
469
22.2k
    }
470
471
184k
    if( p_sys->b_lost_sync ) msg_Warn( p_demux, "found sync code" );
472
184k
    p_sys->b_lost_sync = false;
473
474
184k
    if( p_sys->i_length == VLC_TICK_INVALID && p_sys->b_seekable )
475
391
    {
476
391
        if( !FindLength( p_demux ) )
477
0
            return VLC_DEMUXER_EGENERIC;
478
391
    }
479
480
184k
    if( ( p_pkt = ps_pkt_read( p_demux->s ) ) == NULL )
481
133
    {
482
133
        return VLC_DEMUXER_EOF;
483
133
    }
484
485
184k
    if( p_pkt->i_buffer < 4 )
486
0
    {
487
0
        block_Release( p_pkt );
488
0
        return VLC_DEMUXER_EGENERIC;
489
0
    }
490
491
184k
    const uint8_t i_stream_id = p_pkt->p_buffer[3];
492
184k
    switch( i_stream_id )
493
184k
    {
494
1.07k
    case PS_STREAM_ID_END_STREAM:
495
1.07k
    case STREAM_ID_PADDING:
496
1.07k
        block_Release( p_pkt );
497
1.07k
        break;
498
499
587
    case PS_STREAM_ID_PACK_HEADER:
500
587
        if( !ps_pkt_parse_pack( p_pkt->p_buffer, p_pkt->i_buffer,
501
587
                                &p_sys->i_pack_scr, &i_mux_rate ) )
502
332
        {
503
332
            if( p_sys->i_first_scr == VLC_TICK_INVALID )
504
2
                p_sys->i_first_scr = p_sys->i_pack_scr;
505
332
            CheckPCR( p_sys, p_demux->out, p_sys->i_pack_scr );
506
332
            p_sys->i_scr = p_sys->i_pack_scr;
507
332
            p_sys->i_lastpack_byte = vlc_stream_Tell( p_demux->s );
508
332
            if( !p_sys->b_have_pack ) p_sys->b_have_pack = true;
509
            /* done later on to work around bad vcd/svcd streams */
510
            /* es_out_SetPCR( p_demux->out, p_sys->i_scr ); */
511
332
            if( i_mux_rate > 0 ) p_sys->i_mux_rate = i_mux_rate;
512
332
        }
513
587
        block_Release( p_pkt );
514
587
        break;
515
516
2.13k
    case PS_STREAM_ID_SYSTEM_HEADER:
517
2.13k
        ps_pkt_parse_system( p_pkt->p_buffer, p_pkt->i_buffer,
518
2.13k
                            &p_sys->psm, p_sys->tk );
519
2.13k
        block_Release( p_pkt );
520
2.13k
        break;
521
522
59.8k
    case STREAM_ID_PROGRAM_STREAM_MAP:
523
59.8k
        if( p_sys->psm.i_version == 0xFF )
524
59.8k
            msg_Dbg( p_demux, "contains a PSM");
525
526
59.8k
        ps_psm_fill( &p_sys->psm,
527
59.8k
                     p_pkt->p_buffer, p_pkt->i_buffer,
528
59.8k
                     p_sys->tk );
529
59.8k
        block_Release( p_pkt );
530
59.8k
        break;
531
532
53.2k
    default:
533
        /* Reject non video/audio nor PES */
534
53.2k
        if( i_stream_id < 0xC0 || i_stream_id > 0xEF )
535
2.73k
        {
536
2.73k
            block_Release( p_pkt );
537
2.73k
            break;
538
2.73k
        }
539
        /* fallthrough */
540
105k
    case STREAM_ID_PRIVATE_STREAM_1:
541
118k
    case STREAM_ID_EXTENDED_STREAM_ID:
542
118k
        {
543
118k
            int i_id = ps_pkt_id( p_pkt->p_buffer, p_pkt->i_buffer, p_sys->source );
544
            /* Small heuristic to improve MLP detection from AOB */
545
118k
            if( i_id == PS_AOB_PACKET_ID_MLP &&
546
0
                p_sys->i_aob_mlp_count < 500 )
547
0
            {
548
0
                p_sys->i_aob_mlp_count++;
549
0
            }
550
118k
            else if( i_id == PS_VOB_PACKET_ID_MLP &&
551
405
                     p_sys->i_aob_mlp_count > 0 )
552
0
            {
553
0
                p_sys->i_aob_mlp_count--;
554
0
                i_id = PS_AOB_PACKET_ID_MLP;
555
0
            }
556
557
118k
            bool b_new = false;
558
118k
            ps_track_t *tk = &p_sys->tk[ps_id_to_tk(i_id)];
559
560
118k
            if( !tk->b_configured )
561
16.5k
            {
562
16.5k
                if( !ps_track_fill( tk, &p_sys->psm, i_id,
563
16.5k
                                    p_pkt->p_buffer, p_pkt->i_buffer, false ) )
564
1.97k
                {
565
1.97k
                    if( p_sys->format == IMKH_PS )
566
80
                    {
567
80
                        if( ps_id_to_type( &p_sys->psm , i_id ) == 0x91 )
568
0
                        {
569
0
                            tk->fmt.i_codec = VLC_CODEC_MULAW;
570
0
                            tk->fmt.audio.i_channels = 1;
571
0
                            tk->fmt.audio.i_rate = 8000;
572
0
                        }
573
80
                    }
574
1.89k
                    else
575
                    /* No PSM and no probing yet */
576
1.89k
                    if( p_sys->format == PSMF_PS )
577
0
                    {
578
0
                        if( tk->fmt.i_cat == VIDEO_ES )
579
0
                            tk->fmt.i_codec = VLC_CODEC_H264;
580
#if 0
581
                        if( i_stream_id == PS_STREAM_ID_PRIVATE_STREAM1 )
582
                        {
583
                            es_format_Change( &tk->fmt, AUDIO_ES, VLC_CODEC_ATRAC3P );
584
                            tk->fmt.audio.i_blockalign = 376;
585
                            tk->fmt.audio.i_channels = 2;
586
                            tk->fmt.audio.i_rate = 44100;
587
                        }
588
#endif
589
0
                    }
590
591
1.97k
                    b_new = true;
592
1.97k
                    tk->b_configured = true;
593
1.97k
                    tk->b_updated = true;
594
1.97k
                }
595
14.5k
                else
596
14.5k
                {
597
14.5k
                    msg_Dbg( p_demux, "es id=0x%x format unknown", i_id );
598
14.5k
                }
599
16.5k
            }
600
601
            /* Create all configured/updated ES when seeing a track packet */
602
118k
            if( tk->b_updated )
603
17.4k
                CreateOrUpdateES( p_demux );
604
605
            /* The popular VCD/SVCD subtitling WinSubMux does not
606
             * renumber the SCRs when merging subtitles into the PES */
607
118k
            if( !p_sys->b_bad_scr && p_sys->format == MPEG_PS &&
608
22.5k
                ( tk->fmt.i_codec == VLC_CODEC_OGT ||
609
22.4k
                  tk->fmt.i_codec == VLC_CODEC_CVD ) )
610
261
            {
611
261
                p_sys->b_bad_scr = true;
612
261
                p_sys->i_first_scr = VLC_TICK_INVALID;
613
261
            }
614
615
118k
            if( p_sys->i_pack_scr != VLC_TICK_INVALID && !p_sys->b_bad_scr )
616
61
            {
617
61
                if( (tk->fmt.i_cat == AUDIO_ES || tk->fmt.i_cat == VIDEO_ES) &&
618
34
                    tk->i_first_pts != VLC_TICK_INVALID && tk->i_first_pts - p_sys->i_pack_scr > VLC_TICK_FROM_SEC(2))
619
2
                {
620
2
                    msg_Warn( p_demux, "Incorrect SCR timing offset by of %"PRId64 "ms, disabling",
621
2
                                       MS_FROM_VLC_TICK(tk->i_first_pts - p_sys->i_pack_scr) );
622
2
                    p_sys->b_bad_scr = true; /* Disable Offset SCR */
623
2
                    p_sys->i_first_scr = VLC_TICK_INVALID;
624
2
                }
625
59
                else
626
59
                    es_out_SetPCR( p_demux->out, p_sys->i_pack_scr );
627
61
            }
628
629
118k
            if( tk->b_configured && tk->es &&
630
103k
                !ps_pkt_parse_pes( VLC_OBJECT(p_demux), p_pkt, tk->i_skip ) )
631
55.1k
            {
632
55.1k
                if( tk->fmt.i_cat == AUDIO_ES || tk->fmt.i_cat == VIDEO_ES )
633
15.2k
                {
634
15.2k
                    if( !p_sys->b_bad_scr && p_sys->i_pack_scr != VLC_TICK_INVALID && p_pkt->i_pts != VLC_TICK_INVALID &&
635
0
                        p_sys->i_pack_scr > p_pkt->i_pts + VLC_TICK_FROM_MS(250) )
636
0
                    {
637
0
                        msg_Warn( p_demux, "Incorrect SCR timing in advance of %" PRId64 "ms, disabling",
638
0
                                           MS_FROM_VLC_TICK(p_sys->i_pack_scr - p_pkt->i_pts) );
639
0
                        p_sys->b_bad_scr = true;
640
0
                        p_sys->i_first_scr = VLC_TICK_INVALID;
641
0
                    }
642
643
15.2k
                    if( (p_sys->b_bad_scr || !p_sys->b_have_pack) && !p_sys->i_scr_track_id )
644
223
                    {
645
223
                        p_sys->i_scr_track_id = tk->i_id;
646
223
                    }
647
15.2k
                }
648
649
55.1k
                if( ((!b_new && !p_sys->b_have_pack) || p_sys->b_bad_scr) &&
650
54.7k
                    p_sys->i_scr_track_id == tk->i_id &&
651
6.84k
                    p_pkt->i_pts != VLC_TICK_INVALID )
652
4.29k
                {
653
                    /* A hack to sync the A/V on PES files. */
654
4.29k
                    msg_Dbg( p_demux, "force SCR: %"PRId64, p_pkt->i_pts );
655
4.29k
                    CheckPCR( p_sys, p_demux->out, p_pkt->i_pts );
656
4.29k
                    p_sys->i_scr = p_pkt->i_pts;
657
4.29k
                    if( p_sys->i_first_scr == VLC_TICK_INVALID )
658
143
                        p_sys->i_first_scr = p_sys->i_scr;
659
4.29k
                    es_out_SetPCR( p_demux->out, p_pkt->i_pts );
660
4.29k
                }
661
662
55.1k
                if( p_sys->format == IMKH_PS )
663
2.44k
                {
664
                    /* Synchronization on NVR is always broken */
665
2.44k
                    if( llabs( p_pkt->i_dts - p_sys->i_scr ) > VLC_TICK_FROM_SEC(2) )
666
1.75k
                    {
667
1.75k
                        p_pkt->i_pts = p_pkt->i_pts - p_pkt->i_dts;
668
1.75k
                        p_pkt->i_dts = p_sys->i_scr;
669
1.75k
                        p_pkt->i_pts += p_sys->i_scr;
670
1.75k
                    }
671
2.44k
                }
672
673
55.1k
                if( tk->fmt.i_codec == VLC_CODEC_TELETEXT &&
674
844
                    p_pkt->i_pts == VLC_TICK_INVALID && p_sys->i_scr != VLC_TICK_INVALID )
675
360
                {
676
                    /* Teletext may have missing PTS (ETSI EN 300 472 Annexe A)
677
                     * In this case use the last SCR + 40ms */
678
360
                    p_pkt->i_pts = p_sys->i_scr + VLC_TICK_FROM_MS(40);
679
360
                }
680
681
55.1k
                if( p_pkt->i_pts > p_sys->i_current_pts )
682
460
                {
683
460
                    p_sys->i_current_pts = p_pkt->i_pts;
684
460
                }
685
686
55.1k
                if( tk->i_next_block_flags )
687
4.47k
                {
688
4.47k
                    p_pkt->i_flags = tk->i_next_block_flags;
689
4.47k
                    tk->i_next_block_flags = 0;
690
4.47k
                }
691
#if 0
692
                if( tk->fmt.i_codec == VLC_CODEC_ATRAC3P )
693
                {
694
                    p_pkt->p_buffer += 14;
695
                    p_pkt->i_buffer -= 14;
696
                }
697
#endif
698
55.1k
                es_out_Send( p_demux->out, tk->es, p_pkt );
699
55.1k
            }
700
62.8k
            else
701
62.8k
            {
702
62.8k
                block_Release( p_pkt );
703
62.8k
            }
704
705
118k
            p_sys->i_pack_scr = VLC_TICK_INVALID;
706
118k
        }
707
118k
        break;
708
184k
    }
709
710
184k
    demux_UpdateTitleFromStream( p_demux );
711
184k
    return VLC_DEMUXER_SUCCESS;
712
184k
}
713
714
/*****************************************************************************
715
 * Control:
716
 *****************************************************************************/
717
static int Control( demux_t *p_demux, int i_query, va_list args )
718
0
{
719
0
    demux_sys_t *p_sys = p_demux->p_sys;
720
0
    double f, *pf;
721
0
    uint64_t u64;
722
0
    int i_ret;
723
724
0
    switch( i_query )
725
0
    {
726
0
        case DEMUX_CAN_SEEK:
727
0
            *va_arg( args, bool * ) = p_sys->b_seekable;
728
0
            return VLC_SUCCESS;
729
730
0
        case DEMUX_GET_TITLE:
731
0
            *va_arg( args, int * ) = p_sys->current_title;
732
0
            return VLC_SUCCESS;
733
734
0
        case DEMUX_GET_SEEKPOINT:
735
0
            *va_arg( args, int * ) = p_sys->current_seekpoint;
736
0
            return VLC_SUCCESS;
737
738
0
        case DEMUX_GET_POSITION:
739
0
            pf = va_arg( args, double * );
740
0
            if( vlc_stream_GetSize( p_demux->s, &u64 ) == VLC_SUCCESS )
741
0
            {
742
0
                double current = vlc_stream_Tell( p_demux->s ) - p_sys->i_start_byte;
743
0
                u64 = u64 - p_sys->i_start_byte;
744
0
                *pf = current / (double)u64;
745
0
            }
746
0
            else
747
0
            {
748
0
                *pf = 0.0;
749
0
            }
750
0
            return VLC_SUCCESS;
751
752
0
        case DEMUX_SET_POSITION:
753
0
            f = va_arg( args, double );
754
755
0
            if( vlc_stream_GetSize( p_demux->s, &u64 ) != VLC_SUCCESS )
756
0
                return VLC_EGENERIC;
757
758
0
            u64 = u64 - p_sys->i_start_byte;
759
0
            p_sys->i_current_pts = VLC_TICK_INVALID;
760
0
            p_sys->i_scr = VLC_TICK_INVALID;
761
762
0
            if( p_sys->format == CDXA_PS )
763
0
            {
764
0
                u64 = (uint64_t)(u64  * f); /* Align to sector payload */
765
0
                u64 = p_sys->i_start_byte + u64 - (u64 % CDXA_SECTOR_SIZE) + CDXA_SECTOR_HEADER_SIZE;
766
0
            }
767
0
            else
768
0
            {
769
0
                u64 = p_sys->i_start_byte + (uint64_t)(u64 * f);
770
0
            }
771
772
0
            i_ret = vlc_stream_Seek( p_demux->s, u64 );
773
0
            if( i_ret == VLC_SUCCESS )
774
0
            {
775
0
                NotifyDiscontinuity( p_sys->tk, p_demux->out );
776
0
                return i_ret;
777
0
            }
778
0
            break;
779
780
0
        case DEMUX_GET_TIME:
781
0
            if( p_sys->i_time_track_index >= 0 && p_sys->i_current_pts != VLC_TICK_INVALID )
782
0
            {
783
0
                *va_arg( args, vlc_tick_t * ) = p_sys->i_current_pts - p_sys->tk[p_sys->i_time_track_index].i_first_pts;
784
0
                return VLC_SUCCESS;
785
0
            }
786
0
            if( p_sys->i_first_scr != VLC_TICK_INVALID && p_sys->i_scr != VLC_TICK_INVALID )
787
0
            {
788
0
                vlc_tick_t i_time = p_sys->i_scr - p_sys->i_first_scr;
789
                /* H.222 2.5.2.2 */
790
0
                if( p_sys->i_mux_rate > 0 && p_sys->b_have_pack )
791
0
                {
792
0
                    uint64_t i_offset = vlc_stream_Tell( p_demux->s ) - p_sys->i_lastpack_byte;
793
0
                    i_time += vlc_tick_from_samples(i_offset, p_sys->i_mux_rate * 50);
794
0
                }
795
0
                *va_arg( args, vlc_tick_t * ) = i_time;
796
0
                return VLC_SUCCESS;
797
0
            }
798
0
            *va_arg( args, vlc_tick_t * ) = 0;
799
0
            break;
800
801
0
        case DEMUX_GET_LENGTH:
802
0
            if( p_sys->i_length > VLC_TICK_0 )
803
0
            {
804
0
                *va_arg( args, vlc_tick_t * ) = p_sys->i_length;
805
0
                return VLC_SUCCESS;
806
0
            }
807
0
            else if( p_sys->i_mux_rate > 0 &&
808
0
                     vlc_stream_GetSize( p_demux->s, &u64 ) == VLC_SUCCESS )
809
0
            {
810
0
                *va_arg( args, vlc_tick_t * ) =
811
0
                    vlc_tick_from_samples( u64 - p_sys->i_start_byte / 50, p_sys->i_mux_rate );
812
0
                return VLC_SUCCESS;
813
0
            }
814
0
            *va_arg( args, vlc_tick_t * ) = 0;
815
0
            break;
816
817
0
        case DEMUX_SET_TIME:
818
0
        {
819
0
            if( p_sys->i_time_track_index >= 0 && p_sys->i_current_pts != VLC_TICK_INVALID &&
820
0
                p_sys->i_length > VLC_TICK_0)
821
0
            {
822
0
                vlc_tick_t i_time = va_arg( args, vlc_tick_t );
823
0
                i_time -= p_sys->tk[p_sys->i_time_track_index].i_first_pts;
824
0
                return demux_SetPosition( p_demux, (double) i_time / p_sys->i_length, false );
825
0
            }
826
0
            break;
827
0
        }
828
829
0
        case DEMUX_GET_TITLE_INFO:
830
0
        {
831
0
            struct input_title_t ***v = va_arg( args, struct input_title_t*** );
832
0
            int *c = va_arg( args, int * );
833
834
0
            *va_arg( args, int* ) = 0; /* Title offset */
835
0
            *va_arg( args, int* ) = 0; /* Chapter offset */
836
0
            return vlc_stream_Control( p_demux->s, STREAM_GET_TITLE_INFO, v,
837
0
                                       c );
838
0
        }
839
840
0
        case DEMUX_SET_TITLE:
841
0
            return vlc_stream_vaControl( p_demux->s, STREAM_SET_TITLE, args );
842
843
0
        case DEMUX_SET_SEEKPOINT:
844
0
            return vlc_stream_vaControl( p_demux->s, STREAM_SET_SEEKPOINT,
845
0
                                         args );
846
847
0
        case DEMUX_TEST_AND_CLEAR_FLAGS:
848
0
        {
849
0
            unsigned *restrict flags = va_arg(args, unsigned *);
850
0
            *flags &= p_sys->updates;
851
0
            p_sys->updates &= ~*flags;
852
0
            return VLC_SUCCESS;
853
0
        }
854
855
0
        case DEMUX_GET_META:
856
0
            return vlc_stream_vaControl( p_demux->s, STREAM_GET_META, args );
857
858
0
        case DEMUX_GET_FPS:
859
0
            break;
860
861
0
        case DEMUX_CAN_PAUSE:
862
0
        case DEMUX_SET_PAUSE_STATE:
863
0
        case DEMUX_CAN_CONTROL_PACE:
864
0
        case DEMUX_GET_PTS_DELAY:
865
0
            return demux_vaControlHelper( p_demux->s, 0, -1, 0, 1, i_query, args );
866
867
0
        default:
868
0
            break;
869
870
0
    }
871
0
    return VLC_EGENERIC;
872
0
}
873
874
/*****************************************************************************
875
 * Divers:
876
 *****************************************************************************/
877
878
/* PSResynch: resynch on a system startcode
879
 *  It doesn't skip more than 512 bytes
880
 *  -1 -> error, 0 -> not synch, 1 -> ok
881
 */
882
static int ps_pkt_resynch( stream_t *s, int format, bool b_pack )
883
306k
{
884
306k
    const uint8_t *p_peek;
885
306k
    ssize_t      i_peek;
886
306k
    unsigned int i_skip;
887
888
306k
    if( vlc_stream_Peek( s, &p_peek, 4 ) < 4 )
889
546
    {
890
546
        return -1;
891
546
    }
892
306k
    if( p_peek[0] == 0 && p_peek[1] == 0 && p_peek[2] == 1 &&
893
144k
        p_peek[3] >= PS_STREAM_ID_END_STREAM )
894
137k
    {
895
137k
        return 1;
896
137k
    }
897
898
168k
    if( ( i_peek = vlc_stream_Peek( s, &p_peek, 512 ) ) < 4 )
899
0
    {
900
0
        return -1;
901
0
    }
902
168k
    i_skip = 0;
903
904
168k
    for( ;; )
905
25.6M
    {
906
25.6M
        if( i_peek < 4 )
907
34.7k
        {
908
34.7k
            break;
909
34.7k
        }
910
        /* Handle mid stream 24 bytes padding+CRC creating emulated sync codes with incorrect
911
           PES sizes and frelling up to UINT16_MAX bytes followed by 24 bytes CDXA Header */
912
25.6M
        if( format == CDXA_PS && i_skip == 0 && i_peek >= 48 )
913
1.13k
        {
914
1.13k
            const uint8_t cdxasynccode[12] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
915
1.13k
                                               0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
916
1.13k
            if( !memcmp( &p_peek[24], cdxasynccode, 12 ) )
917
0
            {
918
0
                i_peek -= 48;
919
0
                p_peek += 48;
920
0
                i_skip += 48;
921
0
                continue;
922
0
            }
923
1.13k
        }
924
925
25.6M
        if( p_peek[0] == 0 && p_peek[1] == 0 && p_peek[2] == 1 &&
926
338k
            p_peek[3] >= PS_STREAM_ID_END_STREAM &&
927
137k
            ( !b_pack || p_peek[3] == PS_STREAM_ID_PACK_HEADER ) )
928
133k
        {
929
133k
            return vlc_stream_Read( s, NULL, i_skip ) != i_skip ? -1 : 1;
930
133k
        }
931
932
25.4M
        p_peek++;
933
25.4M
        i_peek--;
934
25.4M
        i_skip++;
935
25.4M
    }
936
34.7k
    return vlc_stream_Read( s, NULL, i_skip ) != i_skip ? -1 : 0;
937
168k
}
938
939
static block_t *ps_pkt_read( stream_t *s )
940
271k
{
941
271k
    const uint8_t *p_peek;
942
271k
    int i_peek = vlc_stream_Peek( s, &p_peek, 14 );
943
271k
    if( i_peek < 4 )
944
0
        return NULL;
945
946
271k
    int i_size = ps_pkt_size( p_peek, i_peek );
947
271k
    if( i_size <= 6 && p_peek[3] > PS_STREAM_ID_PACK_HEADER )
948
134k
    {
949
        /* Special case, search the next start code */
950
134k
        i_size = 6;
951
134k
        for( ;; )
952
145k
        {
953
145k
            i_peek = vlc_stream_Peek( s, &p_peek, i_size + 1024 );
954
145k
            if( i_peek <= i_size + 4 )
955
226
            {
956
226
                return NULL;
957
226
            }
958
20.9M
            while( i_size <= i_peek - 4 )
959
20.9M
            {
960
20.9M
                if( p_peek[i_size] == 0x00 && p_peek[i_size+1] == 0x00 &&
961
2.84M
                    p_peek[i_size+2] == 0x01 && p_peek[i_size+3] >= PS_STREAM_ID_END_STREAM )
962
134k
                {
963
134k
                    return vlc_stream_Block( s, i_size );
964
134k
                }
965
20.8M
                i_size++;
966
20.8M
            }
967
145k
        }
968
134k
    }
969
136k
    else
970
136k
    {
971
        /* Normal case */
972
136k
        return vlc_stream_Block( s, i_size );
973
136k
    }
974
975
0
    return NULL;
976
271k
}