Coverage Report

Created: 2026-05-16 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
19.3k
#define PS_PACKET_PROBE 3
49
461
#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
134
vlc_module_begin ()
60
67
    set_description( N_("MPEG-PS demuxer") )
61
67
    set_shortname( N_("PS") )
62
67
    set_subcategory( SUBCAT_INPUT_DEMUX )
63
67
    set_capability( "demux", 9 )
64
134
    set_callbacks( Open, Close )
65
67
    add_shortcut( "ps" )
66
67
67
    add_bool( "ps-trust-timestamps", true, TIME_TEXT,
68
67
                 TIME_LONGTEXT )
69
67
        change_safe ()
70
67
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
7.04k
{
120
7.04k
    demux_sys_t *p_sys = p_demux->p_sys;
121
122
4.12M
    for( int i = 0; i < PS_TK_COUNT; i++ )
123
4.11M
    {
124
4.11M
        ps_track_t *tk = &p_sys->tk[i];
125
4.11M
        if( !tk->b_updated )
126
4.10M
            continue;
127
128
8.95k
        if( tk->es )
129
5.14k
            es_out_Del( p_demux->out, tk->es );
130
131
8.95k
        if( tk->fmt.i_cat != UNKNOWN_ES )
132
8.95k
            tk->es = es_out_Add( p_demux->out, &tk->fmt );
133
8.95k
        tk->b_updated = false;
134
8.95k
    }
135
7.04k
}
136
137
/*****************************************************************************
138
 * Open
139
 *****************************************************************************/
140
static int Open( vlc_object_t *p_this )
141
19.3k
{
142
19.3k
    demux_t     *p_demux = (demux_t*)p_this;
143
19.3k
    demux_sys_t *p_sys;
144
145
19.3k
    const uint8_t *p_peek;
146
19.3k
    ssize_t i_peek = 0;
147
19.3k
    ssize_t i_offset = 0;
148
19.3k
    int i_skip = 0;
149
19.3k
    unsigned i_max_packets = PS_PACKET_PROBE;
150
19.3k
    int format = MPEG_PS;
151
19.3k
    int i_mux_rate = 0;
152
19.3k
    vlc_tick_t i_length = VLC_TICK_INVALID;
153
154
19.3k
    i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 16 );
155
19.3k
    if( i_peek < 16 )
156
9
        return VLC_EGENERIC;
157
158
19.3k
    if( !memcmp( p_peek, "PSMF", 4 ) &&
159
290
        (GetDWBE( &p_peek[4] ) & 0x30303030) == 0x30303030 )
160
77
    {
161
77
        i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 100 );
162
77
        if( i_peek < 100 )
163
4
            return VLC_EGENERIC;
164
73
        i_skip = i_offset = GetWBE( &p_peek[10] );
165
73
        format = PSMF_PS;
166
73
        msg_Info( p_demux, "Detected PSMF-PS header");
167
73
        i_mux_rate = GetDWBE( &p_peek[96] );
168
73
        if( GetDWBE( &p_peek[86] ) > 0 )
169
70
            i_length = vlc_tick_from_samples( GetDWBE( &p_peek[92] ), GetDWBE( &p_peek[86] ));
170
73
    }
171
19.2k
    else if( !memcmp( p_peek, "IMKH", 4 ) )
172
644
    {
173
644
        msg_Info( p_demux, "Detected Hikvision PVA header");
174
644
        i_skip = 40;
175
644
        format = IMKH_PS;
176
644
        i_max_packets = 0;
177
644
    }
178
18.5k
    else if( !memcmp( p_peek, "RIFF", 4 ) && !memcmp( &p_peek[8], "CDXA", 4 ) )
179
461
    {
180
461
        format = CDXA_PS;
181
461
        i_max_packets = 0; /* We can't probe here */
182
461
        i_skip = CDXA_HEADER_SIZE;
183
461
        msg_Info( p_demux, "Detected CDXA-PS" );
184
        /* FIXME: have a proper way to decap CD sectors or make an access stream filter */
185
461
    }
186
187
21.4k
    for( unsigned i=0; i<i_max_packets; i++ )
188
20.2k
    {
189
20.2k
        if( i_peek < i_offset + 16 )
190
2.14k
        {
191
2.14k
            i_peek = vlc_stream_Peek( p_demux->s, &p_peek, i_offset + 16 );
192
2.14k
            if( i_peek < i_offset + 16 )
193
229
                return VLC_EGENERIC;
194
2.14k
        }
195
196
20.0k
        const uint8_t startcode[3] = { 0x00, 0x00, 0x01 };
197
20.0k
        const uint8_t *p_header = &p_peek[i_offset];
198
20.0k
        if( memcmp( p_header, startcode, 3 ) ||
199
2.92k
           ( (p_header[3] & 0xB0) != 0xB0 &&
200
1.32k
            !(p_header[3] >= 0xC0 && p_header[3] <= 0xEF) &&
201
745
              p_header[3] != STREAM_ID_EXTENDED_STREAM_ID &&
202
745
              p_header[3] != STREAM_ID_PROGRAM_STREAM_DIRECTORY ) )
203
17.8k
            return VLC_EGENERIC;
204
205
2.18k
        ssize_t i_pessize = ps_pkt_size( p_header, 16 );
206
2.18k
        if( i_pessize < 5 )
207
38
            return VLC_EGENERIC;
208
2.14k
        i_offset += i_pessize;
209
2.14k
    }
210
211
1.14k
    if( i_skip && !p_demux->b_preparsing &&
212
1.11k
        vlc_stream_Read( p_demux->s, NULL, i_skip ) != i_skip )
213
8
        return VLC_EGENERIC;
214
215
    /* Fill p_demux field */
216
1.13k
    p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
217
1.13k
    if( !p_sys ) return VLC_ENOMEM;
218
219
1.13k
    p_demux->pf_demux = Demux;
220
1.13k
    p_demux->pf_control = Control;
221
222
    /* Init p_sys */
223
1.13k
    p_sys->i_mux_rate = i_mux_rate;
224
1.13k
    p_sys->i_pack_scr  = VLC_TICK_INVALID;
225
1.13k
    p_sys->i_first_scr = VLC_TICK_INVALID;
226
1.13k
    p_sys->i_scr = VLC_TICK_INVALID;
227
1.13k
    p_sys->i_scr_track_id = 0;
228
1.13k
    p_sys->i_length   = i_length;
229
1.13k
    p_sys->i_current_pts = VLC_TICK_INVALID;
230
1.13k
    p_sys->i_time_track_index = -1;
231
1.13k
    p_sys->i_aob_mlp_count = 0;
232
1.13k
    p_sys->i_start_byte = i_skip;
233
1.13k
    p_sys->i_lastpack_byte = i_skip;
234
235
1.13k
    p_sys->b_lost_sync = false;
236
1.13k
    p_sys->b_have_pack = false;
237
1.13k
    p_sys->b_bad_scr   = false;
238
1.13k
    p_sys->b_seekable  = false;
239
1.13k
    p_sys->format      = format;
240
1.13k
    p_sys->current_title = 0;
241
1.13k
    p_sys->current_seekpoint = 0;
242
1.13k
    p_sys->updates = 0;
243
244
1.13k
    p_sys->source = PS_SOURCE_UNKNOWN;
245
1.13k
    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
1.13k
    vlc_stream_Control( p_demux->s, STREAM_CAN_SEEK, &p_sys->b_seekable );
258
259
1.13k
    ps_psm_init( &p_sys->psm );
260
1.13k
    ps_track_init( p_sys->tk );
261
262
    /* TODO prescanning of ES */
263
264
1.13k
    return VLC_SUCCESS;
265
1.13k
}
266
267
/*****************************************************************************
268
 * Close
269
 *****************************************************************************/
270
static void Close( vlc_object_t *p_this )
271
1.13k
{
272
1.13k
    demux_t     *p_demux = (demux_t*)p_this;
273
1.13k
    demux_sys_t *p_sys = p_demux->p_sys;
274
1.13k
    int i;
275
276
666k
    for( i = 0; i < PS_TK_COUNT; i++ )
277
665k
    {
278
665k
        ps_track_t *tk = &p_sys->tk[i];
279
665k
        es_format_Clean( &tk->fmt );
280
665k
        if( tk->b_configured && tk->es != NULL )
281
3.80k
            es_out_Del( p_demux->out, tk->es );
282
665k
    }
283
284
1.13k
    ps_psm_destroy( &p_sys->psm );
285
286
1.13k
    free( p_sys );
287
1.13k
}
288
289
static int Probe( demux_t *p_demux, bool b_end )
290
100k
{
291
100k
    demux_sys_t *p_sys = p_demux->p_sys;
292
100k
    int i_ret, i_id;
293
100k
    block_t *p_pkt;
294
295
100k
    i_ret = ps_pkt_resynch( p_demux->s, p_sys->format, p_sys->b_have_pack );
296
100k
    if( i_ret < 0 )
297
1.51k
    {
298
1.51k
        return VLC_DEMUXER_EOF;
299
1.51k
    }
300
99.0k
    else if( i_ret == 0 )
301
10.1k
    {
302
10.1k
        if( !p_sys->b_lost_sync )
303
10.1k
            msg_Warn( p_demux, "garbage at input, trying to resync..." );
304
305
10.1k
        p_sys->b_lost_sync = true;
306
10.1k
        return VLC_DEMUXER_SUCCESS;
307
10.1k
    }
308
309
88.9k
    if( p_sys->b_lost_sync ) msg_Warn( p_demux, "found sync code" );
310
88.9k
    p_sys->b_lost_sync = false;
311
312
88.9k
    if( ( p_pkt = ps_pkt_read( p_demux->s ) ) == NULL )
313
238
    {
314
238
        return VLC_DEMUXER_EOF;
315
238
    }
316
317
88.6k
    i_id = ps_pkt_id( p_pkt->p_buffer, p_pkt->i_buffer, p_sys->source );
318
88.6k
    if( i_id >= 0xc0 )
319
68.6k
    {
320
68.6k
        ps_track_t *tk = &p_sys->tk[ps_id_to_tk(i_id)];
321
68.6k
        if( !ps_pkt_parse_pes( VLC_OBJECT(p_demux), p_pkt, tk->i_skip ) &&
322
49.0k
             p_pkt->i_pts != VLC_TICK_INVALID )
323
29.6k
        {
324
29.6k
            if( b_end && (tk->i_last_pts == VLC_TICK_INVALID || p_pkt->i_pts > tk->i_last_pts) )
325
1.93k
            {
326
1.93k
                tk->i_last_pts = p_pkt->i_pts;
327
1.93k
            }
328
27.6k
            else if ( tk->i_first_pts == VLC_TICK_INVALID )
329
1.83k
            {
330
1.83k
                tk->i_first_pts = p_pkt->i_pts;
331
1.83k
            }
332
29.6k
        }
333
68.6k
    }
334
20.0k
    else if( i_id == PS_STREAM_ID_PACK_HEADER )
335
2.37k
    {
336
2.37k
        vlc_tick_t i_scr; int dummy;
337
2.37k
        if( !b_end && !ps_pkt_parse_pack( p_pkt->p_buffer, p_pkt->i_buffer,
338
904
                                          &i_scr, &dummy ) )
339
628
        {
340
628
            if( p_sys->i_first_scr == VLC_TICK_INVALID )
341
229
                p_sys->i_first_scr = i_scr;
342
628
        }
343
2.37k
        p_sys->b_have_pack = true;
344
2.37k
    }
345
346
88.6k
    block_Release( p_pkt );
347
88.6k
    return VLC_DEMUXER_SUCCESS;
348
88.9k
}
349
350
static bool FindLength( demux_t *p_demux )
351
1.11k
{
352
1.11k
    demux_sys_t *p_sys = p_demux->p_sys;
353
354
1.11k
    if( !var_CreateGetBool( p_demux, "ps-trust-timestamps" ) )
355
0
        return true;
356
357
1.11k
    if( p_sys->i_length == VLC_TICK_INVALID ) /* First time */
358
1.11k
    {
359
1.11k
        p_sys->i_length = VLC_TICK_0;
360
        /* Check beginning */
361
1.11k
        int i = 0;
362
1.11k
        uint64_t i_current_pos = vlc_stream_Tell( p_demux->s );
363
23.0k
        while( i < 40 && Probe( p_demux, false ) > 0 ) i++;
364
365
        /* Check end */
366
1.11k
        uint64_t i_size;
367
1.11k
        if( vlc_stream_GetSize( p_demux->s, &i_size ) != VLC_SUCCESS )
368
0
          return false;
369
1.11k
        uint64_t i_end = VLC_CLIP( i_size, 0, 200000 );
370
1.11k
        if( vlc_stream_Seek( p_demux->s, i_size - i_end ) == VLC_SUCCESS )
371
1.11k
        {
372
1.11k
            i = 0;
373
77.9k
            while( i < 400 && Probe( p_demux, true ) > 0 ) i++;
374
1.11k
            if( vlc_stream_Seek( p_demux->s, i_current_pos ) != VLC_SUCCESS )
375
0
                    return false;
376
1.11k
        }
377
0
        else return false;
378
1.11k
    }
379
380
    /* Find the longest track */
381
652k
    for( int i = 0; i < PS_TK_COUNT; i++ )
382
651k
    {
383
651k
        ps_track_t *tk = &p_sys->tk[i];
384
651k
        if( tk->i_first_pts != VLC_TICK_INVALID &&
385
1.83k
            tk->i_last_pts > tk->i_first_pts )
386
146
        {
387
146
            vlc_tick_t i_length = tk->i_last_pts - tk->i_first_pts;
388
146
            if( i_length > p_sys->i_length )
389
145
            {
390
145
                p_sys->i_length = i_length;
391
145
                p_sys->i_time_track_index = i;
392
145
                msg_Dbg( p_demux, "we found a length of: %"PRId64 "s", SEC_FROM_VLC_TICK(p_sys->i_length) );
393
145
            }
394
146
        }
395
651k
    }
396
1.11k
    return true;
397
1.11k
}
398
399
static void NotifyDiscontinuity( ps_track_t *p_tk, es_out_t *out )
400
3.39k
{
401
3.39k
    bool b_selected;
402
1.98M
    for( size_t i = 0; i < PS_TK_COUNT; i++ )
403
1.98M
    {
404
1.98M
        ps_track_t *tk = &p_tk[i];
405
1.98M
        if( tk->es &&
406
15.7k
                es_out_Control( out, ES_OUT_GET_ES_STATE, tk->es, &b_selected ) == VLC_SUCCESS
407
15.7k
                && b_selected )
408
15.7k
        {
409
15.7k
            tk->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY;
410
15.7k
        }
411
1.98M
    }
412
3.39k
}
413
414
static void CheckPCR( demux_sys_t *p_sys, es_out_t *out, vlc_tick_t i_scr )
415
7.73k
{
416
7.73k
    if( p_sys->i_scr != VLC_TICK_INVALID &&
417
7.12k
        llabs( p_sys->i_scr - i_scr ) > VLC_TICK_FROM_SEC(1) )
418
1.42k
        NotifyDiscontinuity( p_sys->tk, out );
419
7.73k
}
420
421
/*****************************************************************************
422
 * Demux:
423
 *****************************************************************************/
424
static int Demux( demux_t *p_demux )
425
129k
{
426
129k
    demux_sys_t *p_sys = p_demux->p_sys;
427
129k
    int i_ret, i_mux_rate;
428
129k
    block_t *p_pkt;
429
430
129k
    i_ret = ps_pkt_resynch( p_demux->s, p_sys->format, p_sys->b_have_pack );
431
129k
    if( i_ret < 0 )
432
940
    {
433
940
        return VLC_DEMUXER_EOF;
434
940
    }
435
128k
    else if( i_ret == 0 )
436
11.0k
    {
437
11.0k
        if( !p_sys->b_lost_sync )
438
1.96k
        {
439
1.96k
            msg_Warn( p_demux, "garbage at input from %"PRIu64", trying to resync...",
440
1.96k
                                vlc_stream_Tell(p_demux->s) );
441
1.96k
            NotifyDiscontinuity( p_sys->tk, p_demux->out );
442
1.96k
        }
443
444
11.0k
        p_sys->b_lost_sync = true;
445
11.0k
        return VLC_DEMUXER_SUCCESS;
446
11.0k
    }
447
448
117k
    if( p_sys->b_lost_sync ) msg_Warn( p_demux, "found sync code" );
449
117k
    p_sys->b_lost_sync = false;
450
451
117k
    if( p_sys->i_length == VLC_TICK_INVALID && p_sys->b_seekable )
452
1.11k
    {
453
1.11k
        if( !FindLength( p_demux ) )
454
0
            return VLC_DEMUXER_EGENERIC;
455
1.11k
    }
456
457
117k
    if( ( p_pkt = ps_pkt_read( p_demux->s ) ) == NULL )
458
199
    {
459
199
        return VLC_DEMUXER_EOF;
460
199
    }
461
462
117k
    if( p_pkt->i_buffer < 4 )
463
0
    {
464
0
        block_Release( p_pkt );
465
0
        return VLC_DEMUXER_EGENERIC;
466
0
    }
467
468
117k
    const uint8_t i_stream_id = p_pkt->p_buffer[3];
469
117k
    switch( i_stream_id )
470
117k
    {
471
2.47k
    case PS_STREAM_ID_END_STREAM:
472
2.50k
    case STREAM_ID_PADDING:
473
2.50k
        block_Release( p_pkt );
474
2.50k
        break;
475
476
1.54k
    case PS_STREAM_ID_PACK_HEADER:
477
1.54k
        if( !ps_pkt_parse_pack( p_pkt->p_buffer, p_pkt->i_buffer,
478
1.54k
                                &p_sys->i_pack_scr, &i_mux_rate ) )
479
1.00k
        {
480
1.00k
            if( p_sys->i_first_scr == VLC_TICK_INVALID )
481
17
                p_sys->i_first_scr = p_sys->i_pack_scr;
482
1.00k
            CheckPCR( p_sys, p_demux->out, p_sys->i_pack_scr );
483
1.00k
            p_sys->i_scr = p_sys->i_pack_scr;
484
1.00k
            p_sys->i_lastpack_byte = vlc_stream_Tell( p_demux->s );
485
1.00k
            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
1.00k
            if( i_mux_rate > 0 ) p_sys->i_mux_rate = i_mux_rate;
489
1.00k
        }
490
1.54k
        block_Release( p_pkt );
491
1.54k
        break;
492
493
1.34k
    case PS_STREAM_ID_SYSTEM_HEADER:
494
1.34k
        ps_pkt_parse_system( p_pkt->p_buffer, p_pkt->i_buffer,
495
1.34k
                            &p_sys->psm, p_sys->tk );
496
1.34k
        block_Release( p_pkt );
497
1.34k
        break;
498
499
16.7k
    case STREAM_ID_PROGRAM_STREAM_MAP:
500
16.7k
        if( p_sys->psm.i_version == 0xFF )
501
16.7k
            msg_Dbg( p_demux, "contains a PSM");
502
503
16.7k
        ps_psm_fill( &p_sys->psm,
504
16.7k
                     p_pkt->p_buffer, p_pkt->i_buffer,
505
16.7k
                     p_sys->tk );
506
16.7k
        block_Release( p_pkt );
507
16.7k
        break;
508
509
33.8k
    default:
510
        /* Reject non video/audio nor PES */
511
33.8k
        if( i_stream_id < 0xC0 || i_stream_id > 0xEF )
512
1.69k
        {
513
1.69k
            block_Release( p_pkt );
514
1.69k
            break;
515
1.69k
        }
516
        /* fallthrough */
517
88.4k
    case STREAM_ID_PRIVATE_STREAM_1:
518
93.2k
    case STREAM_ID_EXTENDED_STREAM_ID:
519
93.2k
        {
520
93.2k
            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
93.2k
            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
93.2k
            else if( i_id == PS_VOB_PACKET_ID_MLP &&
528
308
                     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
93.2k
            bool b_new = false;
535
93.2k
            ps_track_t *tk = &p_sys->tk[ps_id_to_tk(i_id)];
536
537
93.2k
            if( !tk->b_configured )
538
11.1k
            {
539
11.1k
                if( !ps_track_fill( tk, &p_sys->psm, i_id,
540
11.1k
                                    p_pkt->p_buffer, p_pkt->i_buffer, false ) )
541
3.80k
                {
542
3.80k
                    if( p_sys->format == IMKH_PS )
543
1.56k
                    {
544
1.56k
                        if( ps_id_to_type( &p_sys->psm , i_id ) == 0x91 )
545
43
                        {
546
43
                            tk->fmt.i_codec = VLC_CODEC_MULAW;
547
43
                            tk->fmt.audio.i_channels = 1;
548
43
                            tk->fmt.audio.i_rate = 8000;
549
43
                        }
550
1.56k
                    }
551
2.23k
                    else
552
                    /* No PSM and no probing yet */
553
2.23k
                    if( p_sys->format == PSMF_PS )
554
42
                    {
555
42
                        if( tk->fmt.i_cat == VIDEO_ES )
556
18
                            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
42
                    }
567
568
3.80k
                    b_new = true;
569
3.80k
                    tk->b_configured = true;
570
3.80k
                    tk->b_updated = true;
571
3.80k
                }
572
7.36k
                else
573
7.36k
                {
574
7.36k
                    msg_Dbg( p_demux, "es id=0x%x format unknown", i_id );
575
7.36k
                }
576
11.1k
            }
577
578
            /* Create all configured/updated ES when seeing a track packet */
579
93.2k
            if( tk->b_updated )
580
7.04k
                CreateOrUpdateES( p_demux );
581
582
            /* The popular VCD/SVCD subtitling WinSubMux does not
583
             * renumber the SCRs when merging subtitles into the PES */
584
93.2k
            if( !p_sys->b_bad_scr && p_sys->format == MPEG_PS &&
585
592
                ( tk->fmt.i_codec == VLC_CODEC_OGT ||
586
592
                  tk->fmt.i_codec == VLC_CODEC_CVD ) )
587
2
            {
588
2
                p_sys->b_bad_scr = true;
589
2
                p_sys->i_first_scr = VLC_TICK_INVALID;
590
2
            }
591
592
93.2k
            if( p_sys->i_pack_scr != VLC_TICK_INVALID && !p_sys->b_bad_scr )
593
687
            {
594
687
                if( (tk->fmt.i_cat == AUDIO_ES || tk->fmt.i_cat == VIDEO_ES) &&
595
596
                    tk->i_first_pts != VLC_TICK_INVALID && tk->i_first_pts - p_sys->i_pack_scr > VLC_TICK_FROM_SEC(2))
596
17
                {
597
17
                    msg_Warn( p_demux, "Incorrect SCR timing offset by of %"PRId64 "ms, disabling",
598
17
                                       MS_FROM_VLC_TICK(tk->i_first_pts - p_sys->i_pack_scr) );
599
17
                    p_sys->b_bad_scr = true; /* Disable Offset SCR */
600
17
                    p_sys->i_first_scr = VLC_TICK_INVALID;
601
17
                }
602
670
                else
603
670
                    es_out_SetPCR( p_demux->out, p_sys->i_pack_scr );
604
687
            }
605
606
93.2k
            if( tk->b_configured && tk->es &&
607
85.9k
                !ps_pkt_parse_pes( VLC_OBJECT(p_demux), p_pkt, tk->i_skip ) )
608
65.4k
            {
609
65.4k
                if( tk->fmt.i_cat == AUDIO_ES || tk->fmt.i_cat == VIDEO_ES )
610
41.3k
                {
611
41.3k
                    if( !p_sys->b_bad_scr && p_sys->i_pack_scr != VLC_TICK_INVALID && p_pkt->i_pts != VLC_TICK_INVALID &&
612
472
                        p_sys->i_pack_scr > p_pkt->i_pts + VLC_TICK_FROM_MS(250) )
613
116
                    {
614
116
                        msg_Warn( p_demux, "Incorrect SCR timing in advance of %" PRId64 "ms, disabling",
615
116
                                           MS_FROM_VLC_TICK(p_sys->i_pack_scr - p_pkt->i_pts) );
616
116
                        p_sys->b_bad_scr = true;
617
116
                        p_sys->i_first_scr = VLC_TICK_INVALID;
618
116
                    }
619
620
41.3k
                    if( (p_sys->b_bad_scr || !p_sys->b_have_pack) && !p_sys->i_scr_track_id )
621
867
                    {
622
867
                        p_sys->i_scr_track_id = tk->i_id;
623
867
                    }
624
41.3k
                }
625
626
65.4k
                if( ((!b_new && !p_sys->b_have_pack) || p_sys->b_bad_scr) &&
627
61.8k
                    p_sys->i_scr_track_id == tk->i_id &&
628
10.0k
                    p_pkt->i_pts != VLC_TICK_INVALID )
629
6.72k
                {
630
                    /* A hack to sync the A/V on PES files. */
631
6.72k
                    msg_Dbg( p_demux, "force SCR: %"PRId64, p_pkt->i_pts );
632
6.72k
                    CheckPCR( p_sys, p_demux->out, p_pkt->i_pts );
633
6.72k
                    p_sys->i_scr = p_pkt->i_pts;
634
6.72k
                    if( p_sys->i_first_scr == VLC_TICK_INVALID )
635
502
                        p_sys->i_first_scr = p_sys->i_scr;
636
6.72k
                    es_out_SetPCR( p_demux->out, p_pkt->i_pts );
637
6.72k
                }
638
639
65.4k
                if( p_sys->format == IMKH_PS )
640
45.3k
                {
641
                    /* Synchronization on NVR is always broken */
642
45.3k
                    if( llabs( p_pkt->i_dts - p_sys->i_scr ) > VLC_TICK_FROM_SEC(2) )
643
17.6k
                    {
644
17.6k
                        p_pkt->i_pts = p_pkt->i_pts - p_pkt->i_dts;
645
17.6k
                        p_pkt->i_dts = p_sys->i_scr;
646
17.6k
                        p_pkt->i_pts += p_sys->i_scr;
647
17.6k
                    }
648
45.3k
                }
649
650
65.4k
                if( tk->fmt.i_codec == VLC_CODEC_TELETEXT &&
651
1.17k
                    p_pkt->i_pts == VLC_TICK_INVALID && p_sys->i_scr != VLC_TICK_INVALID )
652
107
                {
653
                    /* Teletext may have missing PTS (ETSI EN 300 472 Annexe A)
654
                     * In this case use the last SCR + 40ms */
655
107
                    p_pkt->i_pts = p_sys->i_scr + VLC_TICK_FROM_MS(40);
656
107
                }
657
658
65.4k
                if( p_pkt->i_pts > p_sys->i_current_pts )
659
1.05k
                {
660
1.05k
                    p_sys->i_current_pts = p_pkt->i_pts;
661
1.05k
                }
662
663
65.4k
                if( tk->i_next_block_flags )
664
7.46k
                {
665
7.46k
                    p_pkt->i_flags = tk->i_next_block_flags;
666
7.46k
                    tk->i_next_block_flags = 0;
667
7.46k
                }
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
65.4k
                es_out_Send( p_demux->out, tk->es, p_pkt );
676
65.4k
            }
677
27.8k
            else
678
27.8k
            {
679
27.8k
                block_Release( p_pkt );
680
27.8k
            }
681
682
93.2k
            p_sys->i_pack_scr = VLC_TICK_INVALID;
683
93.2k
        }
684
93.2k
        break;
685
117k
    }
686
687
117k
    demux_UpdateTitleFromStream( p_demux );
688
117k
    return VLC_DEMUXER_SUCCESS;
689
117k
}
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
229k
{
861
229k
    const uint8_t *p_peek;
862
229k
    ssize_t      i_peek;
863
229k
    unsigned int i_skip;
864
865
229k
    if( vlc_stream_Peek( s, &p_peek, 4 ) < 4 )
866
2.45k
    {
867
2.45k
        return -1;
868
2.45k
    }
869
227k
    if( p_peek[0] == 0 && p_peek[1] == 0 && p_peek[2] == 1 &&
870
104k
        p_peek[3] >= PS_STREAM_ID_END_STREAM )
871
102k
    {
872
102k
        return 1;
873
102k
    }
874
875
124k
    if( ( i_peek = vlc_stream_Peek( s, &p_peek, 512 ) ) < 4 )
876
0
    {
877
0
        return -1;
878
0
    }
879
124k
    i_skip = 0;
880
881
124k
    for( ;; )
882
17.7M
    {
883
17.7M
        if( i_peek < 4 )
884
21.1k
        {
885
21.1k
            break;
886
21.1k
        }
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
17.6M
        if( format == CDXA_PS && i_skip == 0 && i_peek >= 48 )
890
50.4k
        {
891
50.4k
            const uint8_t cdxasynccode[12] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
892
50.4k
                                               0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
893
50.4k
            if( !memcmp( &p_peek[24], cdxasynccode, 12 ) )
894
257
            {
895
257
                i_peek -= 48;
896
257
                p_peek += 48;
897
257
                i_skip += 48;
898
257
                continue;
899
257
            }
900
50.4k
        }
901
902
17.6M
        if( p_peek[0] == 0 && p_peek[1] == 0 && p_peek[2] == 1 &&
903
283k
            p_peek[3] >= PS_STREAM_ID_END_STREAM &&
904
118k
            ( !b_pack || p_peek[3] == PS_STREAM_ID_PACK_HEADER ) )
905
103k
        {
906
103k
            return vlc_stream_Read( s, NULL, i_skip ) != i_skip ? -1 : 1;
907
103k
        }
908
909
17.5M
        p_peek++;
910
17.5M
        i_peek--;
911
17.5M
        i_skip++;
912
17.5M
    }
913
21.1k
    return vlc_stream_Read( s, NULL, i_skip ) != i_skip ? -1 : 0;
914
124k
}
915
916
static block_t *ps_pkt_read( stream_t *s )
917
206k
{
918
206k
    const uint8_t *p_peek;
919
206k
    int i_peek = vlc_stream_Peek( s, &p_peek, 14 );
920
206k
    if( i_peek < 4 )
921
0
        return NULL;
922
923
206k
    int i_size = ps_pkt_size( p_peek, i_peek );
924
206k
    if( i_size <= 6 && p_peek[3] > PS_STREAM_ID_PACK_HEADER )
925
97.5k
    {
926
        /* Special case, search the next start code */
927
97.5k
        i_size = 6;
928
97.5k
        for( ;; )
929
111k
        {
930
111k
            i_peek = vlc_stream_Peek( s, &p_peek, i_size + 1024 );
931
111k
            if( i_peek <= i_size + 4 )
932
382
            {
933
382
                return NULL;
934
382
            }
935
24.3M
            while( i_size <= i_peek - 4 )
936
24.3M
            {
937
24.3M
                if( p_peek[i_size] == 0x00 && p_peek[i_size+1] == 0x00 &&
938
4.06M
                    p_peek[i_size+2] == 0x01 && p_peek[i_size+3] >= PS_STREAM_ID_END_STREAM )
939
97.1k
                {
940
97.1k
                    return vlc_stream_Block( s, i_size );
941
97.1k
                }
942
24.2M
                i_size++;
943
24.2M
            }
944
111k
        }
945
97.5k
    }
946
108k
    else
947
108k
    {
948
        /* Normal case */
949
108k
        return vlc_stream_Block( s, i_size );
950
108k
    }
951
952
0
    return NULL;
953
206k
}