ts.c 92.5 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 */
Clément Stenac's avatar
Clément Stenac 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>
Naohiro KORIYAMA's avatar
Naohiro KORIYAMA committed
63

64 65 66
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
Gildas Bazin's avatar
 
Gildas Bazin 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" };
Naohiro KORIYAMA's avatar
Naohiro KORIYAMA 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 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 );
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
    }
Naohiro KORIYAMA's avatar
Naohiro KORIYAMA 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
        int          i_header = 0;
606
        block_t     *p_pkt;
607
        if( !(p_pkt = ReadTSPacket( p_demux )) )
608
        {
609
            return VLC_DEMUXER_EOF;
610
        }
611

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

620 621 622 623 624 625 626
        /* Early reject truncated packets from hw devices */
        if( unlikely(p_pkt->i_buffer < TS_PACKET_SIZE_188) )
        {
            block_Release( p_pkt );
            continue;
        }

627 628 629 630 631 632 633 634 635
        /* 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;
        }

636
        /* Parse the TS packet */
637
        ts_pid_t *p_pid = GetPID( p_sys, PIDGet( p_pkt ) );
638

639 640 641
        if( (p_pkt->p_buffer[1] & 0x40) && (p_pkt->p_buffer[3] & 0x10) &&
            !SCRAMBLED(*p_pid) != !(p_pkt->p_buffer[3] & 0x80) )
        {
642
            UpdatePIDScrambledState( p_demux, p_pid, p_pkt->p_buffer[3] & 0x80 );
643
        }
644

645
        if( !SEEN(p_pid) )
646 647 648 649
        {
            if( p_pid->type == TYPE_FREE )
                msg_Dbg( p_demux, "pid[%d] unknown", p_pid->i_pid );
            p_pid->i_flags |= FLAG_SEEN;
650 651
            if( p_pid->i_pid == 0x01 )
                p_sys->b_valid_scrambling = true;
652 653
        }

654 655 656 657 658
        /* Drop duplicates and invalid (DOES NOT drop corrupted) */
        p_pkt = ProcessTSPacket( p_demux, p_pid, p_pkt, &i_header );
        if( !p_pkt )
            continue;

659 660 661 662 663
        /* 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 );

664
        if ( SCRAMBLED(*p_pid) && !p_demux->p_sys->csa && p_sys->b_valid_scrambling )
665 666 667 668 669
        {
            block_Release( p_pkt );
            continue;
        }

670
        /* Probe streams to build PAT/PMT after MIN_PAT_INTERVAL in case we don't see any PAT */
671
        if( !SEEN( GetPID( p_sys, 0 ) ) &&
672
            (p_pid->probed.i_fourcc == 0 || p_pid->i_pid == p_sys->patfix.i_timesourcepid) &&
673 674 675
            (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 */
        {
676 677
            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 */);
678 679
        }

680
        switch( p_pid->type )
681
        {
682 683
        case TYPE_PAT:
        case TYPE_PMT:
684
            ts_psi_Packet_Push( p_pid, p_pkt->p_buffer );
685
            block_Release( p_pkt );
686 687 688 689
            break;

        case TYPE_PES:
            p_sys->b_end_preparse = true;
690

691
            if( p_sys->es_creation == DELAY_ES ) /* No longer delay ES since that pid's program sends data */
692
            {
693
                msg_Dbg( p_demux, "Creating delayed ES" );
694
                AddAndCreateES( p_demux, p_pid, true );
695
            }
696

697
            /* Emulate HW filter */
698
            if( !p_sys->b_access_control && !(p_pid->i_flags & FLAG_FILTERED) )
699
            {
700 701 702
                /* That packet is for an unselected ES, don't waste time/memory gathering its data */
                block_Release( p_pkt );
                continue;
703
            }
704

705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
            if( p_pid->u.p_pes->transport == TS_TRANSPORT_PES )
            {
                b_frame = GatherPESData( p_demux, p_pid, p_pkt, i_header );
            }
            else if( p_pid->u.p_pes->transport == TS_TRANSPORT_SECTIONS &&
                    !(p_pkt->i_flags & BLOCK_FLAG_SCRAMBLED) )
            {
                ts_sections_processor_Push( p_pid->u.p_pes->p_sections_proc, p_pkt );
                b_frame = true;
            }
            else // pid->u.p_pes->transport == TS_TRANSPORT_IGNORE
            {
                block_Release( p_pkt );
            }

720 721
            break;

722
        case TYPE_SI:
723
            ts_si_Packet_Push( p_pid, p_pkt->p_buffer );
724
            block_Release( p_pkt );
725 726
            break;

727
        case TYPE_PSIP:
728
            ts_psip_Packet_Push( p_pid, p_pkt->p_buffer );
729 730 731
            block_Release( p_pkt );
            break;

732
        case TYPE_CAT:
733
        default:
734
            /* We have to handle PCR if present */
735
            block_Release( p_pkt );
736
            break;
737
        }
738

739
        if( b_frame || ( b_wait_es && p_sys->i_pmt_es > 0 ) )
740 741 742
            break;
    }

743
    demux_UpdateTitleFromStream( p_demux );
744
    return VLC_DEMUXER_SUCCESS;
745 746 747 748 749
}

/*****************************************************************************
 * Control:
 *****************************************************************************/
750
static int EITCurrentEventTime( const ts_pmt_t *p_pmt, demux_sys_t *p_sys,
751
                                time_t *pi_time, time_t *pi_length )
752
{
753
    if( p_sys->i_network_time == 0 || !p_pmt || p_pmt->eit.i_event_length == 0 )
754 755
        return VLC_EGENERIC;

756 757
    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 )
758
    {
759 760 761
        if( pi_length )
            *pi_length = p_pmt->eit.i_event_length;
        if( pi_time )
762
        {
763 764
            *pi_time = p_sys->i_network_time - p_pmt->eit.i_event_start;
            *pi_time += time(NULL) - p_sys->i_network_time_update;
765
        }
766
        return VLC_SUCCESS;
767
    }
768

769 770 771
    return VLC_EGENERIC;
}

772 773 774 775 776 777 778 779 780 781 782 783
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 );
    }
}

784
void UpdatePESFilters( demux_t *p_demux, bool b_all )
785 786
{
    demux_sys_t *p_sys = p_demux->p_sys;
787
    ts_pat_t *p_pat = GetPID(p_sys, 0)->u.p_pat;
788 789 790 791 792 793 794 795

    /* 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 */
796 797
    for( int i=0; i< p_pat->programs.i_size; i++ )
    {
798 799 800 801 802 803 804 805 806 807 808 809 810 811 812
        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;

813
        if( (p_sys->b_default_selection && !p_sys->b_access_control) || b_all )
814
             p_pmt->b_selected = true;
815
        else
816
             p_pmt->b_selected = ProgramIsSelected( p_sys, p_pmt->i_number );
817

818
        if( p_pmt->b_selected )
819
        {
820 821 822
            p_pmt_pid->i_flags |= FLAG_FILTERED;

            for( int j=0; j<p_pmt->e_streams.i_size; j++ )
823
            {
824 825 826 827
                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;
828
                if( !p_pes->b_always_receive && !b_all )
829 830 831
                    HasSelectedES( p_demux->out, p_pes->p_es, p_pmt, &b_stream_selected );

                if( b_stream_selected )
832
                {
833 834
                    msg_Dbg( p_demux, "enabling pid %d from program %d", espid->i_pid, p_pmt->i_number );
                    espid->i_flags |= FLAG_FILTERED;
835 836
                }
            }
837

838 839
            /* Select pcr last in case it is handled by unselected ES */
            if( p_pmt->i_pid_pcr > 0 )
840
            {
841 842
                GetPID(p_sys, p_pmt->i_pid_pcr)->i_flags |= FLAG_FILTERED;
                msg_Dbg( p_demux, "enabling pcr pid %d from program %d", p_pmt->i_pid_pcr, p_pmt->i_number );
843
            }
844
        }
845 846 847 848 849 850 851
    }

    /* Commit HW changes based on flags */
    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;
852

853 854
        UpdateHWFilter( p_sys, p_pmt_pid );
        for( int j=0; j< p_pmt->e_streams.i_size; j++ )
855
        {
856 857 858 859
            ts_pid_t *espid = p_pmt->e_streams.p_elems[j];
            UpdateHWFilter( p_sys, espid );
            if( (espid->i_flags & FLAG_FILTERED) == 0 )
                FlushESBuffer( espid->u.p_pes );
860
        }
861
        UpdateHWFilter( p_sys, GetPID(p_sys, p_pmt->i_pid_pcr) );
862 863 864
    }
}

865 866
static int Control( demux_t *p_demux, int i_query, va_list args )
{
867
    demux_sys_t *p_sys = p_demux->p_sys;
868
    double f, *pf;
869
    bool b_bool, *pb_bool;
870
    int64_t i64;
871
    int64_t *pi64;
872
    int i_int;
873 874
    const ts_pmt_t *p_pmt = NULL;
    const ts_pat_t *p_pat = GetPID(p_sys, 0)->u.p_pat;
875

876
    for( int i=0; i<p_pat->programs.i_size && !p_pmt; i++ )
877
    {
878 879
        if( p_pat->programs.p_elems[i]->u.p_pmt->b_selected )
            p_pmt = p_pat->programs.p_elems[i]->u.p_pmt;
880
    }
881 882 883

    switch( i_query )
    {
884 885 886 887
    case DEMUX_CAN_SEEK:
        *