Coverage Report

Created: 2026-09-01 07:42

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