ts.c 95.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
#include <vlc_input.h>
38

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

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

53
#include "ts.h"
54

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

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

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

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

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

#define PID_TEXT N_("Set id of ES to PID")
85 86 87 88
#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>\"}\'.")
89

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

Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
94 95 96 97
#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).")

98

99 100 101
#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 " \
102
    "decrypting." )
103

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

109 110 111
#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 " \
112
    "time position. If seeking doesn't work property, turn on this option." )
113

114 115 116 117
#define CC_CHECK_TEXT       "Check packets continuity counter"
#define CC_CHECK_LONGTEXT   "Detect discontinuities and drop packet duplicates. " \
                            "(bluRay sources are known broken and have false positives). "

118 119
#define PCR_TEXT N_("Trust in-stream PCR")
#define PCR_LONGTEXT N_("Use the stream PCR as a reference.")
120

121 122 123 124
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
125

126
#define STANDARD_TEXT N_("Digital TV Standard")
127
#define STANDARD_LONGTEXT N_( "Selects mode for digital TV standard. " \
128
                              "This feature affects EPG information and subtitles." )
129

130 131 132 133 134 135
vlc_module_begin ()
    set_description( N_("MPEG Transport Stream demuxer") )
    set_shortname ( "MPEG-TS" )
    set_category( CAT_INPUT )
    set_subcategory( SUBCAT_INPUT_DEMUX )

136 137 138
    add_string( "ts-standard", "auto", STANDARD_TEXT, STANDARD_LONGTEXT, true )
        change_string_list( ts_standards_list, ts_standards_list_text )

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

153
    add_bool( "ts-split-es", true, SPLIT_ES_TEXT, SPLIT_ES_LONGTEXT, false )
154
    add_bool( "ts-seek-percent", false, SEEK_PERCENT_TEXT, SEEK_PERCENT_LONGTEXT, true )
155
    add_bool( "ts-cc-check", true, CC_CHECK_TEXT, CC_CHECK_LONGTEXT, true )
156

157 158
    add_obsolete_bool( "ts-silent" );

159 160 161 162
    set_capability( "demux", 10 )
    set_callbacks( Open, Close )
    add_shortcut( "ts" )
vlc_module_end ()
163 164 165 166

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
167
static int Demux    ( demux_t *p_demux );
168 169
static int Control( demux_t *p_demux, int i_query, va_list args );

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

172
/* Helpers */
173
static bool PIDReferencedByProgram( const ts_pmt_t *, uint16_t );
174
void UpdatePESFilters( demux_t *p_demux, bool b_all );
175
static inline void FlushESBuffer( ts_stream_t *p_pes );
176
static void UpdatePIDScrambledState( demux_t *p_demux, ts_pid_t *p_pid, bool );
177 178 179 180
static inline int PIDGet( block_t *p )
{
    return ( (p->p_buffer[1]&0x1f)<<8 )|p->p_buffer[2];
}
181
static stime_t GetPCR( const block_t * );
182

183 184
static block_t * ProcessTSPacket( demux_t *p_demux, ts_pid_t *pid, block_t *p_pkt, int * );
static bool GatherPESData( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk, size_t );
185
static bool GatherSectionsData( demux_t *p_demux, ts_pid_t *, block_t *, size_t );
186
static void ProgramSetPCR( demux_t *p_demux, ts_pmt_t *p_prg, stime_t i_pcr );
187

188
static block_t* ReadTSPacket( demux_t *p_demux );
189
static int SeekToTime( demux_t *p_demux, const ts_pmt_t *, stime_t time );
190
static void ReadyQueuesPostSeek( demux_t *p_demux );
191
static void PCRHandle( demux_t *p_demux, ts_pid_t *, stime_t );
192
static void PCRFixHandle( demux_t *, ts_pmt_t *, block_t * );
Laurent Aimar's avatar
Laurent Aimar committed
193

194 195 196 197
#define TS_PACKET_SIZE_188 188
#define TS_PACKET_SIZE_192 192
#define TS_PACKET_SIZE_204 204
#define TS_PACKET_SIZE_MAX 204
198
#define TS_HEADER_SIZE 4
199

François Cartegnie's avatar
François Cartegnie committed
200 201 202
#define PROBE_CHUNK_COUNT 500
#define PROBE_MAX         (PROBE_CHUNK_COUNT * 10)

203
static int DetectPacketSize( demux_t *p_demux, unsigned *pi_header_size, int i_offset )
204
{
205
    const uint8_t *p_peek;
206

207
    if( vlc_stream_Peek( p_demux->s,
208
                     &p_peek, i_offset + TS_PACKET_SIZE_MAX ) < i_offset + TS_PACKET_SIZE_MAX )
Laurent Aimar's avatar
Laurent Aimar committed
209
        return -1;
210

Laurent Aimar's avatar
Laurent Aimar committed
211
    for( int i_sync = 0; i_sync < TS_PACKET_SIZE_MAX; i_sync++ )
212
    {
213
        if( p_peek[i_offset + i_sync] != 0x47 )
Laurent Aimar's avatar
Laurent Aimar committed
214 215 216
            continue;

        /* Check next 3 sync bytes */
217
        int i_peek = i_offset + TS_PACKET_SIZE_MAX * 3 + i_sync + 1;
218
        if( ( vlc_stream_Peek( p_demux->s, &p_peek, i_peek ) ) < i_peek )
Laurent Aimar's avatar
Laurent Aimar committed
219
        {
220
            msg_Dbg( p_demux, "cannot peek" );
Laurent Aimar's avatar
Laurent Aimar committed
221 222
            return -1;
        }
223 224 225
        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
226 227 228
        {
            return TS_PACKET_SIZE_188;
        }
229 230 231
        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
232
        {
233 234 235 236
            if( i_sync == 4 )
            {
                *pi_header_size = 4; /* BluRay TS packets have 4-byte header */
            }
Laurent Aimar's avatar
Laurent Aimar committed
237 238
            return TS_PACKET_SIZE_192;
        }
239 240 241
        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
242 243 244
        {
            return TS_PACKET_SIZE_204;
        }
245
    }
246

247
    if( p_demux->obj.force )
Laurent Aimar's avatar
Laurent Aimar committed
248 249 250 251
    {
        msg_Warn( p_demux, "this does not look like a TS stream, continuing" );
        return TS_PACKET_SIZE_188;
    }
252
    msg_Dbg( p_demux, "TS module discarded (lost sync)" );
Laurent Aimar's avatar
Laurent Aimar committed
253 254 255
    return -1;
}

256 257
#define TOPFIELD_HEADER_SIZE 3712

258
static int DetectPVRHeadersAndHeaderSize( demux_t *p_demux, unsigned *pi_header_size, vdr_info_t *p_vdr )
259 260 261 262 263
{
    const uint8_t *p_peek;
    *pi_header_size = 0;
    int i_packet_size = -1;

264
    if( vlc_stream_Peek( p_demux->s,
265 266 267
                     &p_peek, TS_PACKET_SIZE_MAX ) < TS_PACKET_SIZE_MAX )
        return -1;

268
    if( memcmp( p_peek, "TFrc", 4 ) == 0 && p_peek[6] == 0 &&
269
        vlc_stream_Peek( p_demux->s, &p_peek, TOPFIELD_HEADER_SIZE + TS_PACKET_SIZE_MAX )
270 271
            == TOPFIELD_HEADER_SIZE + TS_PACKET_SIZE_MAX )
    {
272
        const int i_service = GetWBE(&p_peek[18]);
273 274 275 276 277 278
        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,
279
             * /doc/Structure%20of%20Recorded%20File%20in%20TF5000PVR%20(Feb%2021%202004).doc on streams.vo
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
             * 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
340
            p_vdr->i_service = i_service;
341 342 343 344 345 346 347 348 349

            return i_packet_size;
            //return TS_PACKET_SIZE_188;
        }
    }

    return DetectPacketSize( p_demux, pi_header_size, 0 );
}

Laurent Aimar's avatar
Laurent Aimar committed
350 351 352 353 354 355 356 357
/*****************************************************************************
 * Open
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;

358 359
    int          i_packet_size;
    unsigned     i_packet_header_size = 0;
Laurent Aimar's avatar
Laurent Aimar committed
360

361
    ts_pid_t    *patpid;
362
    vdr_info_t   vdr = {0};
Laurent Aimar's avatar
Laurent Aimar committed
363 364

    /* Search first sync byte */
365
    i_packet_size = DetectPVRHeadersAndHeaderSize( p_demux, &i_packet_header_size, &vdr );
Laurent Aimar's avatar
Laurent Aimar committed
366 367 368
    if( i_packet_size < 0 )
        return VLC_EGENERIC;

369
    p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
370 371
    if( !p_sys )
        return VLC_ENOMEM;
372
    memset( p_sys, 0, sizeof( demux_sys_t ) );
Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
373
    vlc_mutex_init( &p_sys->csa_lock );
374

375
    p_demux->pf_demux = Demux;
376 377 378
    p_demux->pf_control = Control;

    /* Init p_sys field */
379 380 381
    p_sys->b_end_preparse = false;
    ARRAY_INIT( p_sys->programs );
    p_sys->b_default_selection = false;
382 383
    p_sys->i_network_time = 0;
    p_sys->i_network_time_update = 0;
384

385 386
    p_sys->vdr = vdr;

387 388 389
    p_sys->arib.b25stream = NULL;
    p_sys->stream = p_demux->s;

390 391
    p_sys->b_broken_charset = false;

392
    ts_pid_list_Init( &p_sys->pids );
393

394
    p_sys->i_packet_size = i_packet_size;
395
    p_sys->i_packet_header_size = i_packet_header_size;
396
    p_sys->i_ts_read = 50;
397
    p_sys->csa = NULL;
398
    p_sys->b_start_record = false;
399

400 401
    vlc_dictionary_init( &p_sys->attachments, 0 );

402 403 404 405
    p_sys->patfix.i_first_dts = -1;
    p_sys->patfix.i_timesourcepid = 0;
    p_sys->patfix.status = PAT_WAITING;

406
    /* Init PAT handler */
407
    patpid = GetPID(p_sys, 0);
408
    if ( !PIDSetup( p_demux, TYPE_PAT, patpid, NULL ) )
409 410 411 412 413
    {
        vlc_mutex_destroy( &p_sys->csa_lock );
        free( p_sys );
        return VLC_ENOMEM;
    }
414
    if( !ts_psi_PAT_Attach( patpid, p_demux ) )
415
    {
416
        PIDRelease( p_demux, patpid );
417 418 419 420
        vlc_mutex_destroy( &p_sys->csa_lock );
        free( p_sys );
        return VLC_EGENERIC;
    }
421

422 423
    p_sys->b_access_control = true;
    p_sys->b_access_control = ( VLC_SUCCESS == SetPIDFilter( p_sys, patpid, true ) );
424

425
    p_sys->i_pmt_es = 0;
426
    p_sys->seltype = PROGRAM_AUTO_DEFAULT;
427

428
    /* Read config */
429
    p_sys->b_es_id_pid = var_CreateGetBool( p_demux, "ts-es-id-pid" );
430
    p_sys->i_next_extraid = 1;
431

432 433
    p_sys->b_trust_pcr = var_CreateGetBool( p_demux, "ts-trust-pcr" );

434
    /* We handle description of an extra PMT */
Rafaël Carré's avatar
Rafaël Carré committed
435
    char* psz_string = var_CreateGetString( p_demux, "ts-extra-pmt" );
436
    p_sys->b_user_pmt = false;
437 438 439
    if( psz_string && *psz_string )
        UserPmt( p_demux, psz_string );
    free( psz_string );
440

441 442
    psz_string = var_CreateGetStringCommand( p_demux, "ts-csa-ck" );
    if( psz_string && *psz_string )
443
    {
444
        int i_res;
445
        char* psz_csa2;
446 447 448

        p_sys->csa = csa_New();

449 450 451
        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
452
        {
453
            if( csa_SetCW( (vlc_object_t*)p_demux, p_sys->csa, psz_csa2, false ) != VLC_SUCCESS )
Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
454
            {
455
                csa_SetCW( (vlc_object_t*)p_demux, p_sys->csa, psz_string, false );
Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
456 457 458 459
            }
        }
        else if ( i_res == VLC_SUCCESS )
        {
460
            csa_SetCW( (vlc_object_t*)p_demux, p_sys->csa, psz_string, false );
Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
461 462
        }
        else
463
        {
464
            csa_Delete( p_sys->csa );
Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
465
            p_sys->csa = NULL;
466
        }
467 468

        if( p_sys->csa )
469
        {
Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
470 471 472
            var_AddCallback( p_demux, "ts-csa-ck", ChangeKeyCallback, (void *)1 );
            var_AddCallback( p_demux, "ts-csa2-ck", ChangeKeyCallback, NULL );

473 474
            int i_pkt = var_CreateGetInteger( p_demux, "ts-csa-pkt" );
            if( i_pkt < 4 || i_pkt > 188 )
475
            {
476
                msg_Err( p_demux, "wrong packet size %d specified.", i_pkt );
477 478
                msg_Warn( p_demux, "using default packet size of 188 bytes" );
                p_sys->i_csa_pkt_size = 188;
479
            }
480 481
            else
                p_sys->i_csa_pkt_size = i_pkt;
482
            msg_Dbg( p_demux, "decrypting %d bytes of packet", p_sys->i_csa_pkt_size );
483
        }
484
        free( psz_csa2 );
485
    }
486
    free( psz_string );
487

488
    p_sys->b_split_es = var_InheritBool( p_demux, "ts-split-es" );
489

490
    p_sys->b_canseek = false;
491
    p_sys->b_canfastseek = false;
492
    p_sys->b_ignore_time_for_positions = var_InheritBool( p_demux, "ts-seek-percent" );
493
    p_sys->b_cc_check = var_InheritBool( p_demux, "ts-cc-check" );
494

495 496 497
    p_sys->standard = TS_STANDARD_AUTO;
    char *psz_standard = var_InheritString( p_demux, "ts-standard" );
    if( psz_standard )
498
    {
499 500 501 502 503 504 505 506 507 508 509 510 511
        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 &&
512 513
       ( !strncasecmp( p_demux->psz_url, "atsc", 4 ) ||
         !strncasecmp( p_demux->psz_url, "usdigital", 9 ) ) )
514 515
    {
        TsChangeStandard( p_sys, TS_STANDARD_ATSC );
516
    }
nkoriyama's avatar
nkoriyama committed
517

518 519 520
    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 );
521

522 523
    /* Preparse time */
    if( p_sys->b_canseek )
524
    {
525 526 527 528
        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;
529
        p_sys->es_creation = DELAY_ES;
530
    }
531 532
    else
        p_sys->es_creation = ( p_sys->b_access_control ? CREATE_ES : DELAY_ES );
533

534 535 536 537 538 539
    return VLC_SUCCESS;
}

/*****************************************************************************
 * Close
 *****************************************************************************/
540 541 542 543 544 545
static void FreeDictAttachment( void *p_value, void *p_obj )
{
    VLC_UNUSED(p_obj);
    vlc_input_attachment_Delete( (input_attachment_t *) p_value );
}

546 547 548 549 550
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;

551
    PIDRelease( p_demux, GetPID(p_sys, 0) );
552

Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
553
    vlc_mutex_lock( &p_sys->csa_lock );
554 555
    if( p_sys->csa )
    {
556
        var_DelCallback( p_demux, "ts-csa-ck", ChangeKeyCallback, (void *)1 );
Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
557
        var_DelCallback( p_demux, "ts-csa2-ck", ChangeKeyCallback, NULL );
558 559
        csa_Delete( p_sys->csa );
    }
Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
560
    vlc_mutex_unlock( &p_sys->csa_lock );
561

562
    ARRAY_RESET( p_sys->programs );
563

564 565 566 567 568
#ifdef HAVE_ARIBB24
    if ( p_sys->arib.p_instance )
        arib_instance_destroy( p_sys->arib.p_instance );
#endif

569 570
    if ( p_sys->arib.b25stream )
    {
571
        p_sys->arib.b25stream->s = NULL; /* don't chain kill demuxer's source */
572
        vlc_stream_Delete( p_sys->arib.b25stream );
573 574
    }

Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
575
    vlc_mutex_destroy( &p_sys->csa_lock );
576 577

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

580 581 582
    /* Clear up attachments */
    vlc_dictionary_clear( &p_sys->attachments, FreeDictAttachment, NULL );

583 584 585
    free( p_sys );
}

Kaloyan Kovachev's avatar
Kaloyan Kovachev committed
586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
/*****************************************************************************
 * 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;
}

608 609 610 611 612 613
/*****************************************************************************
 * Demux:
 *****************************************************************************/
static int Demux( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
614
    bool b_wait_es = p_sys->i_pmt_es <= 0;
615

616
    /* If we had no PAT within MIN_PAT_INTERVAL, create PAT/PMT from probed streams */
617 618
    if( p_sys->i_pmt_es == 0 && !SEEN(GetPID(p_sys, 0)) && p_sys->patfix.status == PAT_MISSING )
    {
619
        MissingPATPMTFixup( p_demux );
620
        p_sys->patfix.status = PAT_FIXTRIED;
621
        GetPID(p_sys, 0)->u.p_pat->b_generated = true;
622
    }
623

624
    /* We read at most 100 TS packet or until a frame is completed */
625
    for( unsigned i_pkt = 0; i_pkt < p_sys->i_ts_read; i_pkt++ )
626
    {
627
        bool         b_frame = false;
628
        int          i_header = 0;
629
        block_t     *p_pkt;
630
        if( !(p_pkt = ReadTSPacket( p_demux )) )
631
        {
632
            return VLC_DEMUXER_EOF;
633
        }
634

635 636 637
        if( p_sys->b_start_record )
        {
            /* Enable recording once synchronized */
638 639
            vlc_stream_Control( p_sys->stream, STREAM_SET_RECORD_STATE, true,
                                "ts" );
640 641 642
            p_sys->b_start_record = false;
        }

643 644 645 646 647 648 649
        /* Early reject truncated packets from hw devices */
        if( unlikely(p_pkt->i_buffer < TS_PACKET_SIZE_188) )
        {
            block_Release( p_pkt );
            continue;
        }

650 651 652 653 654 655 656 657 658
        /* Reject any fully uncorrected packet. Even PID can be incorrect */
        if( p_pkt->p_buffer[1]&0x80 )
        {
            msg_Dbg( p_demux, "transport_error_indicator set (pid=%d)",
                     PIDGet( p_pkt ) );
            block_Release( p_pkt );
            continue;
        }

659
        /* Parse the TS packet */
660
        ts_pid_t *p_pid = GetPID( p_sys, PIDGet( p_pkt ) );
661
        if( !SEEN(p_pid) )
662 663 664 665
        {
            if( p_pid->type == TYPE_FREE )
                msg_Dbg( p_demux, "pid[%d] unknown", p_pid->i_pid );
            p_pid->i_flags |= FLAG_SEEN;
666 667
            if( p_pid->i_pid == 0x01 )
                p_sys->b_valid_scrambling = true;
668 669
        }

670 671 672 673 674
        /* Drop duplicates and invalid (DOES NOT drop corrupted) */
        p_pkt = ProcessTSPacket( p_demux, p_pid, p_pkt, &i_header );
        if( !p_pkt )
            continue;

675 676 677 678 679
        if( !SCRAMBLED(*p_pid) != !(p_pkt->i_flags & BLOCK_FLAG_SCRAMBLED) )
        {
            UpdatePIDScrambledState( p_demux, p_pid, p_pkt->i_flags & BLOCK_FLAG_SCRAMBLED );
        }

680
        /* Adaptation field cannot be scrambled */
681 682
        stime_t i_pcr = GetPCR( p_pkt );
        if( i_pcr >= 0 )
683 684
            PCRHandle( p_demux, p_pid, i_pcr );

685
        /* Probe streams to build PAT/PMT after MIN_PAT_INTERVAL in case we don't see any PAT */
686
        if( !SEEN( GetPID( p_sys, 0 ) ) &&
687
            (p_pid->probed.i_fourcc == 0 || p_pid->i_pid == p_sys->patfix.i_timesourcepid) &&
688 689 690
            (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 */
        {
691 692
            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 */);
693 694
        }

695
        switch( p_pid->type )
696
        {
697 698
        case TYPE_PAT:
        case TYPE_PMT:
699
            /* PAT and PMT are not allowed to be scrambled */
700
            ts_psi_Packet_Push( p_pid, p_pkt->p_buffer );
701
            block_Release( p_pkt );
702 703
            break;

704
        case TYPE_STREAM:
705
            p_sys->b_end_preparse = true;
706

707
            if( p_sys->es_creation == DELAY_ES ) /* No longer delay ES since that pid's program sends data */
708
            {
709
                msg_Dbg( p_demux, "Creating delayed ES" );
710
                AddAndCreateES( p_demux, p_pid, true );
711
                UpdatePESFilters( p_demux, p_sys->seltype == PROGRAM_ALL );
712
            }
713

714
            /* Emulate HW filter */
715
            if( !p_sys->b_access_control && !(p_pid->i_flags & FLAG_FILTERED) )
716
            {
717 718 719
                /* That packet is for an unselected ES, don't waste time/memory gathering its data */
                block_Release( p_pkt );
                continue;
720
            }
721

722
            if( p_pid->u.p_stream->transport == TS_TRANSPORT_PES )
723 724 725
            {
                b_frame = GatherPESData( p_demux, p_pid, p_pkt, i_header );
            }
726
            else if( p_pid->u.p_stream->transport == TS_TRANSPORT_SECTIONS )
727
            {
728
                b_frame = GatherSectionsData( p_demux, p_pid, p_pkt, i_header );
729 730 731 732 733 734
            }
            else // pid->u.p_pes->transport == TS_TRANSPORT_IGNORE
            {
                block_Release( p_pkt );
            }

735 736
            break;

737
        case TYPE_SI:
738 739
            if( (p_pkt->i_flags & (BLOCK_FLAG_SCRAMBLED|BLOCK_FLAG_CORRUPTED)) == 0 )
                ts_si_Packet_Push( p_pid, p_pkt->p_buffer );
740
            block_Release( p_pkt );
741 742
            break;

743
        case TYPE_PSIP:
744 745
            if( (p_pkt->i_flags & (BLOCK_FLAG_SCRAMBLED|BLOCK_FLAG_CORRUPTED)) == 0 )
                ts_psip_Packet_Push( p_pid, p_pkt->p_buffer );
746 747 748
            block_Release( p_pkt );
            break;

749
        case TYPE_CAT:
750
        default:
751
            /* We have to handle PCR if present */
752
            block_Release( p_pkt );
753
            break;
754
        }
755

756
        if( b_frame || ( b_wait_es && p_sys->i_pmt_es > 0 ) )
757 758 759
            break;
    }

760
    demux_UpdateTitleFromStream( p_demux );
761
    return VLC_DEMUXER_SUCCESS;
762 763 764 765 766
}

/*****************************************************************************
 * Control:
 *****************************************************************************/
767
static int EITCurrentEventTime( const ts_pmt_t *p_pmt, demux_sys_t *p_sys,
768
                                time_t *pi_time, time_t *pi_length )
769
{
770
    if( p_sys->i_network_time == 0 || !p_pmt || p_pmt->eit.i_event_length == 0 )
771 772
        return VLC_EGENERIC;

773 774
    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 )