ts.c 90.8 KB
Newer Older
1 2 3
/*****************************************************************************
 * ts.c: Transport Stream input module for VLC.
 *****************************************************************************
4
 * Copyright (C) 2004-2016 VLC authors and VideoLAN
5
 * $Id$
6 7
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8
 *          Jean-Paul Saman <jpsaman #_at_# m2x.nl>
9
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
10 11 12
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
13 14 15 16
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
17 18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
19
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
20 21 22
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 24 25 26 27
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
28

29 30 31 32
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

33
#include <vlc_common.h>
34
#include <vlc_plugin.h>
35
#include <vlc_access.h>    /* DVB-specific things */
zorglub's avatar
zorglub committed
36
#include <vlc_demux.h>
37

38 39 40 41
#include "ts_pid.h"
#include "ts_streams.h"
#include "ts_streams_private.h"
#include "ts_psi.h"
42
#include "ts_si.h"
43
#include "ts_psip.h"
44

45 46
#include "ts_hotfixes.h"
#include "ts_sl.h"
47
#include "ts_metadata.h"
48 49 50
#include "sections.h"
#include "pes.h"
#include "timestamps.h"
51

52
#include "ts.h"
53

54
#include "../../codec/scte18.h"
55
#include "../opus.h"
56
#include "../../mux/mpeg/csa.h"
57

58 59 60 61
#ifdef HAVE_ARIBB24
 #include <aribb24/aribb24.h>
#endif

62
#include <assert.h>
nkoriyama's avatar
nkoriyama committed
63

64 65 66
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
67 68
static int  Open  ( vlc_object_t * );
static void Close ( vlc_object_t * );
69

70 71 72
/* TODO
 * - Rename "extra pmt" to "user pmt"
 * - Update extra pmt description
73
 *      pmt_pid[:pmt_number][=pid_description[,pid_description]]
74 75 76
 *      where pid_description could take 3 forms:
 *          1. pid:pcr (to force the pcr pid)
 *          2. pid:stream_type
77
 *          3. pid:type=fourcc where type=(video|audio|spu)
78
 */
79 80
#define PMT_TEXT N_("Extra PMT")
#define PMT_LONGTEXT N_( \
81
  "Allows a user to specify an extra pmt (pmt_pid=pid:stream_type[,...])." )
82 83

#define PID_TEXT N_("Set id of ES to PID")
84 85 86 87
#define PID_LONGTEXT N_("Set the internal ID of each elementary stream" \
                       " handled by VLC to the same value as the PID in" \
                       " the TS stream, instead of 1, 2, 3, etc. Useful to" \
                       " do \'#duplicate{..., select=\"es=<pid>\"}\'.")
88

89 90 91
#define CSA_TEXT N_("CSA Key")
#define CSA_LONGTEXT N_("CSA encryption key. This must be a " \
  "16 char string (8 hexadecimal bytes).")
92

Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
93 94 95 96
#define CSA2_TEXT N_("Second CSA Key")
#define CSA2_LONGTEXT N_("The even CSA encryption key. This must be a " \
  "16 char string (8 hexadecimal bytes).")

97

98 99 100 101 102
#define CPKT_TEXT N_("Packet size in bytes to decrypt")
#define CPKT_LONGTEXT N_("Specify the size of the TS packet to decrypt. " \
    "The decryption routines subtract the TS-header from the value before " \
    "decrypting. " )

103 104
#define SPLIT_ES_TEXT N_("Separate sub-streams")
#define SPLIT_ES_LONGTEXT N_( \
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
105
    "Separate teletex/dvbs pages into independent ES. " \
Rémi Denis-Courmont's avatar
Typos  
Rémi Denis-Courmont committed
106
    "It can be useful to turn off this option when using stream output." )
107

108 109 110
#define SEEK_PERCENT_TEXT N_("Seek based on percent not time")
#define SEEK_PERCENT_LONGTEXT N_( \
    "Seek and position based on a percent byte position, not a PCR generated " \
111
    "time position. If seeking doesn't work property, turn on this option." )
112

113 114
#define PCR_TEXT N_("Trust in-stream PCR")
#define PCR_LONGTEXT N_("Use the stream PCR as a reference.")
115

116 117 118 119
static const char *const ts_standards_list[] =
    { "auto", "mpeg", "dvb", "arib", "atsc", "tdmb" };
static const char *const ts_standards_list_text[] =
  { N_("Auto"), "MPEG", "DVB", "ARIB", "ATSC", "T-DMB" };
nkoriyama's avatar
nkoriyama committed
120

121 122 123
#define STANDARD_TEXT N_("Digital TV Standard")
#define STANDARD_LONGTEXT N_( "Selects mode for digital TV standard." \
                              "This feature affects EPG information and subtitles." )
124

125 126 127 128 129 130
vlc_module_begin ()
    set_description( N_("MPEG Transport Stream demuxer") )
    set_shortname ( "MPEG-TS" )
    set_category( CAT_INPUT )
    set_subcategory( SUBCAT_INPUT_DEMUX )

131 132 133
    add_string( "ts-standard", "auto", STANDARD_TEXT, STANDARD_LONGTEXT, true )
        change_string_list( ts_standards_list, ts_standards_list_text )

134
    add_string( "ts-extra-pmt", NULL, PMT_TEXT, PMT_LONGTEXT, true )
135 136
    add_bool( "ts-trust-pcr", true, PCR_TEXT, PCR_LONGTEXT, true )
        change_safe()
137
    add_bool( "ts-es-id-pid", true, PID_TEXT, PID_LONGTEXT, true )
138
        change_safe()
Rafaël Carré's avatar
Rafaël Carré committed
139 140
    add_obsolete_string( "ts-out" ) /* since 2.2.0 */
    add_obsolete_integer( "ts-out-mtu" ) /* since 2.2.0 */
141
    add_string( "ts-csa-ck", NULL, CSA_TEXT, CSA_LONGTEXT, true )
142
        change_safe()
143
    add_string( "ts-csa2-ck", NULL, CSA2_TEXT, CSA2_LONGTEXT, true )
144
        change_safe()
145
    add_integer( "ts-csa-pkt", 188, CPKT_TEXT, CPKT_LONGTEXT, true )
146 147
        change_safe()

148
    add_bool( "ts-split-es", true, SPLIT_ES_TEXT, SPLIT_ES_LONGTEXT, false )
149
    add_bool( "ts-seek-percent", false, SEEK_PERCENT_TEXT, SEEK_PERCENT_LONGTEXT, true )
150

151 152
    add_obsolete_bool( "ts-silent" );

153 154 155 156
    set_capability( "demux", 10 )
    set_callbacks( Open, Close )
    add_shortcut( "ts" )
vlc_module_end ()
157 158 159 160

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
161
static int Demux    ( demux_t *p_demux );
162 163
static int Control( demux_t *p_demux, int i_query, va_list args );

Laurent Aimar's avatar
Laurent Aimar committed
164
static int ChangeKeyCallback( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * );
165

166
/* Helpers */
167
static bool PIDReferencedByProgram( const ts_pmt_t *, uint16_t );
168
void UpdatePESFilters( demux_t *p_demux, bool b_all );
169
static inline void FlushESBuffer( ts_pes_t *p_pes );
170
static void UpdatePIDScrambledState( demux_t *p_demux, ts_pid_t *p_pid, bool );
171 172 173 174
static inline int PIDGet( block_t *p )
{
    return ( (p->p_buffer[1]&0x1f)<<8 )|p->p_buffer[2];
}
175
static mtime_t GetPCR( const block_t * );
176

177 178
static bool ProcessTSPacket( demux_t *p_demux, ts_pid_t *pid, block_t *p_pkt );
static bool GatherPESData( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk, size_t, bool );
179
static void ProgramSetPCR( demux_t *p_demux, ts_pmt_t *p_prg, mtime_t i_pcr );
180

181
static block_t* ReadTSPacket( demux_t *p_demux );
182
static int SeekToTime( demux_t *p_demux, const ts_pmt_t *, int64_t time );
183
static void ReadyQueuesPostSeek( demux_t *p_demux );
184
static void PCRHandle( demux_t *p_demux, ts_pid_t *, mtime_t );
185
static void PCRFixHandle( demux_t *, ts_pmt_t *, block_t * );
Laurent Aimar's avatar
Laurent Aimar committed
186

187 188 189 190
#define TS_PACKET_SIZE_188 188
#define TS_PACKET_SIZE_192 192
#define TS_PACKET_SIZE_204 204
#define TS_PACKET_SIZE_MAX 204
191
#define TS_HEADER_SIZE 4
192

193
static int DetectPacketSize( demux_t *p_demux, unsigned *pi_header_size, int i_offset )
194
{
195
    const uint8_t *p_peek;
196

197
    if( vlc_stream_Peek( p_demux->s,
198
                     &p_peek, i_offset + TS_PACKET_SIZE_MAX ) < i_offset + TS_PACKET_SIZE_MAX )
Laurent Aimar's avatar
Laurent Aimar committed
199
        return -1;
200

Laurent Aimar's avatar
Laurent Aimar committed
201
    for( int i_sync = 0; i_sync < TS_PACKET_SIZE_MAX; i_sync++ )
202
    {
203
        if( p_peek[i_offset + i_sync] != 0x47 )
Laurent Aimar's avatar
Laurent Aimar committed
204 205 206
            continue;

        /* Check next 3 sync bytes */
207
        int i_peek = i_offset + TS_PACKET_SIZE_MAX * 3 + i_sync + 1;
208
        if( ( vlc_stream_Peek( p_demux->s, &p_peek, i_peek ) ) < i_peek )
Laurent Aimar's avatar
Laurent Aimar committed
209 210 211 212
        {
            msg_Err( p_demux, "cannot peek" );
            return -1;
        }
213 214 215
        if( p_peek[i_offset + i_sync + 1 * TS_PACKET_SIZE_188] == 0x47 &&
            p_peek[i_offset + i_sync + 2 * TS_PACKET_SIZE_188] == 0x47 &&
            p_peek[i_offset + i_sync + 3 * TS_PACKET_SIZE_188] == 0x47 )
Laurent Aimar's avatar
Laurent Aimar committed
216 217 218
        {
            return TS_PACKET_SIZE_188;
        }
219 220 221
        else if( p_peek[i_offset + i_sync + 1 * TS_PACKET_SIZE_192] == 0x47 &&
                 p_peek[i_offset + i_sync + 2 * TS_PACKET_SIZE_192] == 0x47 &&
                 p_peek[i_offset + i_sync + 3 * TS_PACKET_SIZE_192] == 0x47 )
Laurent Aimar's avatar
Laurent Aimar committed
222
        {
223 224 225 226
            if( i_sync == 4 )
            {
                *pi_header_size = 4; /* BluRay TS packets have 4-byte header */
            }
Laurent Aimar's avatar
Laurent Aimar committed
227 228
            return TS_PACKET_SIZE_192;
        }
229 230 231
        else if( p_peek[i_offset + i_sync + 1 * TS_PACKET_SIZE_204] == 0x47 &&
                 p_peek[i_offset + i_sync + 2 * TS_PACKET_SIZE_204] == 0x47 &&
                 p_peek[i_offset + i_sync + 3 * TS_PACKET_SIZE_204] == 0x47 )
Laurent Aimar's avatar
Laurent Aimar committed
232 233 234
        {
            return TS_PACKET_SIZE_204;
        }
235
    }
236

237
    if( p_demux->obj.force )
Laurent Aimar's avatar
Laurent Aimar committed
238 239 240 241
    {
        msg_Warn( p_demux, "this does not look like a TS stream, continuing" );
        return TS_PACKET_SIZE_188;
    }
242
    msg_Dbg( p_demux, "TS module discarded (lost sync)" );
Laurent Aimar's avatar
Laurent Aimar committed
243 244 245
    return -1;
}

246 247
#define TOPFIELD_HEADER_SIZE 3712

248
static int DetectPVRHeadersAndHeaderSize( demux_t *p_demux, unsigned *pi_header_size, vdr_info_t *p_vdr )
249 250 251 252 253
{
    const uint8_t *p_peek;
    *pi_header_size = 0;
    int i_packet_size = -1;

254
    if( vlc_stream_Peek( p_demux->s,
255 256 257 258
                     &p_peek, TS_PACKET_SIZE_MAX ) < TS_PACKET_SIZE_MAX )
        return -1;

    if( memcmp( p_peek, "TFrc", 4 ) == 0 &&
259
        p_peek[6] == 0 && memcmp( &p_peek[53], "\x80\x00\x00", 4 ) == 0 &&
260
        vlc_stream_Peek( p_demux->s, &p_peek, TOPFIELD_HEADER_SIZE + TS_PACKET_SIZE_MAX )
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
            == TOPFIELD_HEADER_SIZE + TS_PACKET_SIZE_MAX )
    {
        i_packet_size = DetectPacketSize( p_demux, pi_header_size, TOPFIELD_HEADER_SIZE );
        if( i_packet_size != -1 )
        {
            msg_Dbg( p_demux, "this is a topfield file" );
#if 0
            /* I used the TF5000PVR 2004 Firmware .doc header documentation,
             * http://www.i-topfield.com/data/product/firmware/Structure%20of%20Recorded%20File%20in%20TF5000PVR%20(Feb%2021%202004).doc
             * but after the filename the offsets seem to be incorrect.  - DJ */
            int i_duration, i_name;
            char *psz_name = xmalloc(25);
            char *psz_event_name;
            char *psz_event_text = xmalloc(130);
            char *psz_ext_text = xmalloc(1025);

            // 2 bytes version Uimsbf (4,5)
            // 2 bytes reserved (6,7)
            // 2 bytes duration in minutes Uimsbf (8,9(
            i_duration = (int) (p_peek[8] << 8) | p_peek[9];
            msg_Dbg( p_demux, "Topfield recording length: +/- %d minutes", i_duration);
            // 2 bytes service number in channel list (10, 11)
            // 2 bytes service type Bslbf 0=TV 1=Radio Bslb (12, 13)
            // 4 bytes of reserved + tuner info (14,15,16,17)
            // 2 bytes of Service ID  Bslbf (18,19)
            // 2 bytes of PMT PID  Uimsbf (20,21)
            // 2 bytes of PCR PID  Uimsbf (22,23)
            // 2 bytes of Video PID  Uimsbf (24,25)
            // 2 bytes of Audio PID  Uimsbf (26,27)
            // 24 bytes filename Bslbf
            memcpy( psz_name, &p_peek[28], 24 );
            psz_name[24] = '\0';
            msg_Dbg( p_demux, "recordingname=%s", psz_name );
            // 1 byte of sat index Uimsbf  (52)
            // 3 bytes (1 bit of polarity Bslbf +23 bits reserved)
            // 4 bytes of freq. Uimsbf (56,57,58,59)
            // 2 bytes of symbol rate Uimsbf (60,61)
            // 2 bytes of TS stream ID Uimsbf (62,63)
            // 4 bytes reserved
            // 2 bytes reserved
            // 2 bytes duration Uimsbf (70,71)
            //i_duration = (int) (p_peek[70] << 8) | p_peek[71];
            //msg_Dbg( p_demux, "Topfield 2nd duration field: +/- %d minutes", i_duration);
            // 4 bytes EventID Uimsbf (72-75)
            // 8 bytes of Start and End time info (76-83)
            // 1 byte reserved (84)
            // 1 byte event name length Uimsbf (89)
            i_name = (int)(p_peek[89]&~0x81);
            msg_Dbg( p_demux, "event name length = %d", i_name);
            psz_event_name = xmalloc( i_name+1 );
            // 1 byte parental rating (90)
            // 129 bytes of event text
            memcpy( psz_event_name, &p_peek[91], i_name );
            psz_event_name[i_name] = '\0';
            memcpy( psz_event_text, &p_peek[91+i_name], 129-i_name );
            psz_event_text[129-i_name] = '\0';
            msg_Dbg( p_demux, "event name=%s", psz_event_name );
            msg_Dbg( p_demux, "event text=%s", psz_event_text );
            // 12 bytes reserved (220)
            // 6 bytes reserved
            // 2 bytes Event Text Length Uimsbf
            // 4 bytes EventID Uimsbf
            // FIXME We just have 613 bytes. not enough for this entire text
            // 1024 bytes Extended Event Text Bslbf
            memcpy( psz_ext_text, p_peek+372, 1024 );
            psz_ext_text[1024] = '\0';
            msg_Dbg( p_demux, "extended event text=%s", psz_ext_text );
            // 52 bytes reserved Bslbf
#endif
            p_vdr->i_service = GetWBE(&p_peek[18]);

            return i_packet_size;
            //return TS_PACKET_SIZE_188;
        }
    }

    return DetectPacketSize( p_demux, pi_header_size, 0 );
}

Laurent Aimar's avatar
Laurent Aimar committed
340 341 342 343 344 345 346 347
/*****************************************************************************
 * Open
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;

348 349
    int          i_packet_size;
    unsigned     i_packet_header_size = 0;
Laurent Aimar's avatar
Laurent Aimar committed
350

351
    ts_pid_t    *patpid;
352
    vdr_info_t   vdr = {0};
Laurent Aimar's avatar
Laurent Aimar committed
353 354

    /* Search first sync byte */
355
    i_packet_size = DetectPVRHeadersAndHeaderSize( p_demux, &i_packet_header_size, &vdr );
Laurent Aimar's avatar
Laurent Aimar committed
356 357 358
    if( i_packet_size < 0 )
        return VLC_EGENERIC;

359
    p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
360 361
    if( !p_sys )
        return VLC_ENOMEM;
362
    memset( p_sys, 0, sizeof( demux_sys_t ) );
Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
363
    vlc_mutex_init( &p_sys->csa_lock );
364

365
    p_demux->pf_demux = Demux;
366 367 368
    p_demux->pf_control = Control;

    /* Init p_sys field */
369 370 371
    p_sys->b_end_preparse = false;
    ARRAY_INIT( p_sys->programs );
    p_sys->b_default_selection = false;
372 373
    p_sys->i_network_time = 0;
    p_sys->i_network_time_update = 0;
374

375 376
    p_sys->vdr = vdr;

377 378 379
    p_sys->arib.b25stream = NULL;
    p_sys->stream = p_demux->s;

380 381
    p_sys->b_broken_charset = false;

382
    ts_pid_list_Init( &p_sys->pids );
383

384
    p_sys->i_packet_size = i_packet_size;
385
    p_sys->i_packet_header_size = i_packet_header_size;
386
    p_sys->i_ts_read = 50;
387
    p_sys->csa = NULL;
388
    p_sys->b_start_record = false;
389

390 391 392 393
    p_sys->patfix.i_first_dts = -1;
    p_sys->patfix.i_timesourcepid = 0;
    p_sys->patfix.status = PAT_WAITING;

394
    /* Init PAT handler */
395
    patpid = GetPID(p_sys, 0);
396
    if ( !PIDSetup( p_demux, TYPE_PAT, patpid, NULL ) )
397 398 399 400 401
    {
        vlc_mutex_destroy( &p_sys->csa_lock );
        free( p_sys );
        return VLC_ENOMEM;
    }
402
    if( !ts_psi_PAT_Attach( patpid, p_demux ) )
403
    {
404
        PIDRelease( p_demux, patpid );
405 406 407 408
        vlc_mutex_destroy( &p_sys->csa_lock );
        free( p_sys );
        return VLC_EGENERIC;
    }
409

410 411
    p_sys->b_access_control = true;
    p_sys->b_access_control = ( VLC_SUCCESS == SetPIDFilter( p_sys, patpid, true ) );
412

413
    p_sys->i_pmt_es = 0;
414
    p_sys->b_es_all = false;
415

416
    /* Read config */
417
    p_sys->b_es_id_pid = var_CreateGetBool( p_demux, "ts-es-id-pid" );
418
    p_sys->i_next_extraid = 1;
419

420 421
    p_sys->b_trust_pcr = var_CreateGetBool( p_demux, "ts-trust-pcr" );

422
    /* We handle description of an extra PMT */
Rafaël Carré's avatar
Rafaël Carré committed
423
    char* psz_string = var_CreateGetString( p_demux, "ts-extra-pmt" );
424
    p_sys->b_user_pmt = false;
425 426 427
    if( psz_string && *psz_string )
        UserPmt( p_demux, psz_string );
    free( psz_string );
428

429 430
    psz_string = var_CreateGetStringCommand( p_demux, "ts-csa-ck" );
    if( psz_string && *psz_string )
431
    {
432
        int i_res;
433
        char* psz_csa2;
434 435 436

        p_sys->csa = csa_New();

437 438 439
        psz_csa2 = var_CreateGetStringCommand( p_demux, "ts-csa2-ck" );
        i_res = csa_SetCW( (vlc_object_t*)p_demux, p_sys->csa, psz_string, true );
        if( i_res == VLC_SUCCESS && psz_csa2 && *psz_csa2 )
Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
440
        {
441
            if( csa_SetCW( (vlc_object_t*)p_demux, p_sys->csa, psz_csa2, false ) != VLC_SUCCESS )
Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
442
            {
443
                csa_SetCW( (vlc_object_t*)p_demux, p_sys->csa, psz_string, false );
Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
444 445 446 447
            }
        }
        else if ( i_res == VLC_SUCCESS )
        {
448
            csa_SetCW( (vlc_object_t*)p_demux, p_sys->csa, psz_string, false );
Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
449 450
        }
        else
451
        {
452
            csa_Delete( p_sys->csa );
Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
453
            p_sys->csa = NULL;
454
        }
455 456

        if( p_sys->csa )
457
        {
Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
458 459 460
            var_AddCallback( p_demux, "ts-csa-ck", ChangeKeyCallback, (void *)1 );
            var_AddCallback( p_demux, "ts-csa2-ck", ChangeKeyCallback, NULL );

461 462
            int i_pkt = var_CreateGetInteger( p_demux, "ts-csa-pkt" );
            if( i_pkt < 4 || i_pkt > 188 )
463
            {
464
                msg_Err( p_demux, "wrong packet size %d specified.", i_pkt );
465 466
                msg_Warn( p_demux, "using default packet size of 188 bytes" );
                p_sys->i_csa_pkt_size = 188;
467
            }
468 469
            else
                p_sys->i_csa_pkt_size = i_pkt;
470
            msg_Dbg( p_demux, "decrypting %d bytes of packet", p_sys->i_csa_pkt_size );
471
        }
472
        free( psz_csa2 );
473
    }
474
    free( psz_string );
475

476
    p_sys->b_split_es = var_InheritBool( p_demux, "ts-split-es" );
477

478
    p_sys->b_canseek = false;
479
    p_sys->b_canfastseek = false;
480
    p_sys->b_ignore_time_for_positions = var_InheritBool( p_demux, "ts-seek-percent" );
481

482 483 484
    p_sys->standard = TS_STANDARD_AUTO;
    char *psz_standard = var_InheritString( p_demux, "ts-standard" );
    if( psz_standard )
485
    {
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
        for( unsigned i=0; i<ARRAY_SIZE(ts_standards_list); i++ )
        {
            if( !strcmp( psz_standard, ts_standards_list[i] ) )
            {
                TsChangeStandard( p_sys, TS_STANDARD_AUTO + i );
                msg_Dbg( p_demux, "Standard set to %s", ts_standards_list_text[i] );
                break;
            }
        }
        free( psz_standard );
    }

    if( p_sys->standard == TS_STANDARD_AUTO &&
       ( !strcmp( p_demux->psz_access, "atsc" ) ||
         !strcmp( p_demux->psz_access, "usdigital" ) ) )
    {
        TsChangeStandard( p_sys, TS_STANDARD_ATSC );
503
    }
nkoriyama's avatar
nkoriyama committed
504

505 506 507
    vlc_stream_Control( p_sys->stream, STREAM_CAN_SEEK, &p_sys->b_canseek );
    vlc_stream_Control( p_sys->stream, STREAM_CAN_FASTSEEK,
                        &p_sys->b_canfastseek );
508

509 510
    /* Preparse time */
    if( p_sys->b_canseek )
511
    {
512 513 514 515
        p_sys->es_creation = NO_ES;
        while( !p_sys->i_pmt_es && !p_sys->b_end_preparse )
            if( Demux( p_demux ) != VLC_DEMUXER_SUCCESS )
                break;
516
        p_sys->es_creation = DELAY_ES;
517
    }
518 519
    else
        p_sys->es_creation = ( p_sys->b_access_control ? CREATE_ES : DELAY_ES );
520

521 522 523 524 525 526 527 528 529 530 531
    return VLC_SUCCESS;
}

/*****************************************************************************
 * Close
 *****************************************************************************/
static void Close( vlc_object_t *p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys = p_demux->p_sys;

532
    PIDRelease( p_demux, GetPID(p_sys, 0) );
533

Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
534
    vlc_mutex_lock( &p_sys->csa_lock );
535 536
    if( p_sys->csa )
    {
537
        var_DelCallback( p_demux, "ts-csa-ck", ChangeKeyCallback, (void *)1 );
Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
538
        var_DelCallback( p_demux, "ts-csa2-ck", ChangeKeyCallback, NULL );
539 540
        csa_Delete( p_sys->csa );
    }
Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
541
    vlc_mutex_unlock( &p_sys->csa_lock );
542

543
    ARRAY_RESET( p_sys->programs );
544

545 546 547 548 549
#ifdef HAVE_ARIBB24
    if ( p_sys->arib.p_instance )
        arib_instance_destroy( p_sys->arib.p_instance );
#endif

550 551 552
    if ( p_sys->arib.b25stream )
    {
        p_sys->arib.b25stream->p_source = NULL; /* don't chain kill demuxer's source */
553
        vlc_stream_Delete( p_sys->arib.b25stream );
554 555
    }

Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
556
    vlc_mutex_destroy( &p_sys->csa_lock );
557 558

    /* Release all non default pids */
559
    ts_pid_list_Release( p_demux, &p_sys->pids );
560

561 562 563
    free( p_sys );
}

Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
/*****************************************************************************
 * ChangeKeyCallback: called when changing the odd encryption key on the fly.
 *****************************************************************************/
static int ChangeKeyCallback( vlc_object_t *p_this, char const *psz_cmd,
                           vlc_value_t oldval, vlc_value_t newval,
                           void *p_data )
{
    VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys = p_demux->p_sys;
    int         i_tmp = (intptr_t)p_data;

    vlc_mutex_lock( &p_sys->csa_lock );
    if ( i_tmp )
        i_tmp = csa_SetCW( p_this, p_sys->csa, newval.psz_string, true );
    else
        i_tmp = csa_SetCW( p_this, p_sys->csa, newval.psz_string, false );

    vlc_mutex_unlock( &p_sys->csa_lock );
    return i_tmp;
}

586 587 588 589 590 591
/*****************************************************************************
 * Demux:
 *****************************************************************************/
static int Demux( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
592
    bool b_wait_es = p_sys->i_pmt_es <= 0;
593

594
    /* If we had no PAT within MIN_PAT_INTERVAL, create PAT/PMT from probed streams */
595 596
    if( p_sys->i_pmt_es == 0 && !SEEN(GetPID(p_sys, 0)) && p_sys->patfix.status == PAT_MISSING )
    {
597
        MissingPATPMTFixup( p_demux );
598 599
        p_sys->patfix.status = PAT_FIXTRIED;
    }
600

601
    /* We read at most 100 TS packet or until a frame is completed */
602
    for( unsigned i_pkt = 0; i_pkt < p_sys->i_ts_read; i_pkt++ )
603
    {
604
        bool         b_frame = false;
605
        block_t     *p_pkt;
606
        if( !(p_pkt = ReadTSPacket( p_demux )) )
607
        {
608
            return VLC_DEMUXER_EOF;
609
        }
610

611 612 613
        if( p_sys->b_start_record )
        {
            /* Enable recording once synchronized */
614 615
            vlc_stream_Control( p_sys->stream, STREAM_SET_RECORD_STATE, true,
                                "ts" );
616 617 618
            p_sys->b_start_record = false;
        }

619
        /* Parse the TS packet */
620
        ts_pid_t *p_pid = GetPID( p_sys, PIDGet( p_pkt ) );
621

622 623 624
        if( (p_pkt->p_buffer[1] & 0x40) && (p_pkt->p_buffer[3] & 0x10) &&
            !SCRAMBLED(*p_pid) != !(p_pkt->p_buffer[3] & 0x80) )
        {
625
            UpdatePIDScrambledState( p_demux, p_pid, p_pkt->p_buffer[3] & 0x80 );
626
        }
627

628
        if( !SEEN(p_pid) )
629 630 631 632
        {
            if( p_pid->type == TYPE_FREE )
                msg_Dbg( p_demux, "pid[%d] unknown", p_pid->i_pid );
            p_pid->i_flags |= FLAG_SEEN;
633 634
            if( p_pid->i_pid == 0x01 )
                p_sys->b_valid_scrambling = true;
635 636
        }

637 638 639 640 641
        /* Adaptation field cannot be scrambled */
        mtime_t i_pcr = GetPCR( p_pkt );
        if( i_pcr > VLC_TS_INVALID )
            PCRHandle( p_demux, p_pid, i_pcr );

642
        if ( SCRAMBLED(*p_pid) && !p_demux->p_sys->csa && p_sys->b_valid_scrambling )
643 644 645 646 647
        {
            block_Release( p_pkt );
            continue;
        }

648
        /* Probe streams to build PAT/PMT after MIN_PAT_INTERVAL in case we don't see any PAT */
649
        if( !SEEN( GetPID( p_sys, 0 ) ) &&
650 651 652 653
            (p_pid->probed.i_type == 0 || p_pid->i_pid == p_sys->patfix.i_timesourcepid) &&
            (p_pkt->p_buffer[1] & 0xC0) == 0x40 && /* Payload start but not corrupt */
            (p_pkt->p_buffer[3] & 0xD0) == 0x10 )  /* Has payload but is not encrypted */
        {
654 655
            ProbePES( p_demux, p_pid, p_pkt->p_buffer + TS_HEADER_SIZE,
                      p_pkt->i_buffer - TS_HEADER_SIZE, p_pkt->p_buffer[3] & 0x20 /* Adaptation field */);
656 657
        }

658
        switch( p_pid->type )
659
        {
660 661
        case TYPE_PAT:
        case TYPE_PMT:
662
            ts_psi_Packet_Push( p_pid, p_pkt->p_buffer );
663
            block_Release( p_pkt );
664 665 666 667
            break;

        case TYPE_PES:
            p_sys->b_end_preparse = true;
668

669
            if( p_sys->es_creation == DELAY_ES ) /* No longer delay ES since that pid's program sends data */
670
            {
671
                msg_Dbg( p_demux, "Creating delayed ES" );
672
                AddAndCreateES( p_demux, p_pid, true );
673
            }
674

675
            /* Emulate HW filter */
676
            if( !p_sys->b_access_control && !(p_pid->i_flags & FLAG_FILTERED) )
677
            {
678 679 680
                /* That packet is for an unselected ES, don't waste time/memory gathering its data */
                block_Release( p_pkt );
                continue;
681
            }
682

683
            b_frame = ProcessTSPacket( p_demux, p_pid, p_pkt );
684 685
            break;

686
        case TYPE_SI:
687
            ts_si_Packet_Push( p_pid, p_pkt->p_buffer );
688
            block_Release( p_pkt );
689 690
            break;

691
        case TYPE_PSIP:
692
            ts_psip_Packet_Push( p_pid, p_pkt->p_buffer );
693 694 695
            block_Release( p_pkt );
            break;

696
        case TYPE_CAT:
697
        default:
698
            /* We have to handle PCR if present */
699
            block_Release( p_pkt );
700
            break;
701
        }
702

703
        if( b_frame || ( b_wait_es && p_sys->i_pmt_es > 0 ) )
704 705 706
            break;
    }

707
    demux_UpdateTitleFromStream( p_demux );
708
    return VLC_DEMUXER_SUCCESS;
709 710 711 712 713
}

/*****************************************************************************
 * Control:
 *****************************************************************************/
714
static int EITCurrentEventTime( const ts_pmt_t *p_pmt, demux_sys_t *p_sys,
715
                                time_t *pi_time, time_t *pi_length )
716
{
717
    if( p_sys->i_network_time == 0 || !p_pmt || p_pmt->eit.i_event_length == 0 )
718 719
        return VLC_EGENERIC;

720 721
    if( p_pmt->eit.i_event_start <= p_sys->i_network_time &&
        p_sys->i_network_time < p_pmt->eit.i_event_start + p_pmt->eit.i_event_length )
722
    {
723 724 725
        if( pi_length )
            *pi_length = p_pmt->eit.i_event_length;
        if( pi_time )
726
        {
727 728
            *pi_time = p_sys->i_network_time - p_pmt->eit.i_event_start;
            *pi_time += time(NULL) - p_sys->i_network_time_update;
729
        }
730
        return VLC_SUCCESS;
731
    }
732

733 734 735
    return VLC_EGENERIC;
}

736 737 738 739 740 741 742 743 744 745 746 747
static inline void HasSelectedES( es_out_t *out, const ts_pes_es_t *p_es,
                                  const ts_pmt_t *p_pmt, bool *pb_stream_selected )
{
    for( ; p_es && !*pb_stream_selected; p_es = p_es->p_next )
    {
        if( p_es->id )
            es_out_Control( out, ES_OUT_GET_ES_STATE,
                            p_es->id, pb_stream_selected );
        HasSelectedES( out, p_es->p_extraes, p_pmt, pb_stream_selected );
    }
}

748
void UpdatePESFilters( demux_t *p_demux, bool b_all )
749 750
{
    demux_sys_t *p_sys = p_demux->p_sys;
751
    ts_pat_t *p_pat = GetPID(p_sys, 0)->u.p_pat;
752 753 754 755 756 757 758 759

    /* We need 3 pass to avoid loss on deselect/relesect with hw filters and
       because pid could be shared and its state altered by another unselected pmt
       First clear flag on every referenced pid
       Then add flag if non on each selected pmt/pcr and active es
       Then commit it at hardware level if any */

    /* clear selection flag on every pmt referenced pid */
760 761
    for( int i=0; i< p_pat->programs.i_size; i++ )
    {
762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
        ts_pid_t *p_pmt_pid = p_pat->programs.p_elems[i];
        ts_pmt_t *p_pmt = p_pmt_pid->u.p_pmt;

        p_pmt_pid->i_flags &= ~FLAG_FILTERED;
        for( int j=0; j< p_pmt->e_streams.i_size; j++ )
            p_pmt->e_streams.p_elems[j]->i_flags &= ~FLAG_FILTERED;
        GetPID(p_sys, p_pmt->i_pid_pcr)->i_flags &= ~FLAG_FILTERED;
    }

    /* set selection flag on selected pmt referenced pid with active es */
    for( int i=0; i< p_pat->programs.i_size; i++ )
    {
        ts_pid_t *p_pmt_pid = p_pat->programs.p_elems[i];
        ts_pmt_t *p_pmt = p_pmt_pid->u.p_pmt;

777
        if( (p_sys->b_default_selection && !p_sys->b_access_control) || b_all )
778
             p_pmt->b_selected = true;
779
        else
780
             p_pmt->b_selected = ProgramIsSelected( p_sys, p_pmt->i_number );
781

782
        if( p_pmt->b_selected )
783
        {
784 785 786
            p_pmt_pid->i_flags |= FLAG_FILTERED;

            for( int j=0; j<p_pmt->e_streams.i_size; j++ )
787
            {
788 789 790 791
                ts_pid_t *espid = p_pmt->e_streams.p_elems[j];
                ts_pes_t *p_pes = espid->u.p_pes;

                bool b_stream_selected = true;
792
                if( !p_pes->b_always_receive && !b_all )
793 794 795
                    HasSelectedES( p_demux->out, p_pes->p_es, p_pmt, &b_stream_selected );

                if( b_stream_selected )
796
                {
797 798
                    msg_Dbg( p_demux, "enabling pid %d from program %d", espid->i_pid, p_pmt->i_number );
                    espid->i_flags |= FLAG_FILTERED;
799 800
                }
            }
801

802 803
            /* Select pcr last in case it is handled by unselected ES */
            if( p_pmt->i_pid_pcr > 0 )
804
            {