ts.c 61.5 KB
Newer Older
1
/*****************************************************************************
2
 * ts.c: MPEG-II TS Muxer
3 4
 *****************************************************************************
 * Copyright (C) 2001, 2002 VideoLAN
5
 * $Id$
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *          Eric Petit <titer@videolan.org>
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (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
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <stdlib.h>

#include <vlc/vlc.h>
#include <vlc/input.h>
#include <vlc/sout.h>

35 36
#include "iso_lang.h"

37 38
#include "bits.h"
#include "pes.h"
39
#include "csa.h"
40

41
#if defined MODULE_NAME_IS_mux_ts_dvbpsi
ipkiss's avatar
ipkiss committed
42
#   ifdef HAVE_DVBPSI_DR_H
43 44 45 46 47
#       include <dvbpsi/dvbpsi.h>
#       include <dvbpsi/descriptor.h>
#       include <dvbpsi/pat.h>
#       include <dvbpsi/pmt.h>
#       include <dvbpsi/dr.h>
48
#       include <dvbpsi/psi.h>
ipkiss's avatar
ipkiss committed
49 50 51 52 53 54
#   else
#       include "dvbpsi.h"
#       include "descriptor.h"
#       include "tables/pat.h"
#       include "tables/pmt.h"
#       include "descriptors/dr.h"
55
#       include "psi.h"
ipkiss's avatar
ipkiss committed
56
#   endif
57 58
#endif

59 60 61 62 63
/*
 * TODO:
 *  - check PCR frequency requirement
 *  - check PAT/PMT  "        "
 *  - check PCR/PCR "soft"
64 65
 *  - check if "registration" descriptor : "AC-3" should be a program
 *    descriptor or an es one. (xine want an es one)
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
 *
 *  - remove creation of PAT/PMT without dvbpsi
 *  - ?
 * FIXME:
 *  - subtitle support is far from perfect. I expect some subtitles drop
 *    if they arrive a bit late
 *    (We cannot rely on the fact that the fifo should be full)
 */
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
static int     Open   ( vlc_object_t * );
static void    Close  ( vlc_object_t * );

vlc_module_begin();
#if defined MODULE_NAME_IS_mux_ts
    set_description( _("TS muxer") );
    set_capability( "sout mux", 100 );
    add_shortcut( "ts" );
    add_shortcut( "ts_nodvbpsi" );
#elif defined MODULE_NAME_IS_mux_ts_dvbpsi
    set_description( _("TS muxer (libdvbpsi)") );
    set_capability( "sout mux", 120 );
    add_shortcut( "ts" );
    add_shortcut( "ts_dvbpsi" );
#endif
    set_callbacks( Open, Close );
vlc_module_end();

/*****************************************************************************
96
 * Local data structures
97
 *****************************************************************************/
98 99
#define SOUT_BUFFER_FLAGS_PRIVATE_PCR  ( 1 << BLOCK_FLAG_PRIVATE_SHIFT )
#define SOUT_BUFFER_FLAGS_PRIVATE_CSA  ( 2 << BLOCK_FLAG_PRIVATE_SHIFT )
100 101 102
typedef struct
{
    int           i_depth;
103 104
    block_t *p_first;
    block_t **pp_last;
105 106 107 108 109 110 111 112
} sout_buffer_chain_t;

static inline void BufferChainInit  ( sout_buffer_chain_t *c )
{
    c->i_depth = 0;
    c->p_first = NULL;
    c->pp_last = &c->p_first;
}
113
static inline void BufferChainAppend( sout_buffer_chain_t *c, block_t *b )
114 115 116 117 118 119 120 121 122 123 124
{
    *c->pp_last = b;
    c->i_depth++;

    while( b->p_next )
    {
        b = b->p_next;
        c->i_depth++;
    }
    c->pp_last = &b->p_next;
}
125
static inline block_t *BufferChainGet( sout_buffer_chain_t *c )
126
{
127
    block_t *b = c->p_first;
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142

    if( b )
    {
        c->i_depth--;
        c->p_first = b->p_next;

        if( c->p_first == NULL )
        {
            c->pp_last = &c->p_first;
        }

        b->p_next = NULL;
    }
    return b;
}
143
static inline block_t *BufferChainPeek( sout_buffer_chain_t *c )
144
{
145
    block_t *b = c->p_first;
146 147 148

    return b;
}
149 150
static inline void BufferChainClean( sout_instance_t *p_sout, sout_buffer_chain_t *c )
{
151
    block_t *b;
152 153 154

    while( ( b = BufferChainGet( c ) ) )
    {
155
        block_Release( b );
156 157 158
    }
    BufferChainInit( c );
}
159

160
typedef struct ts_stream_t
161 162 163 164 165
{
    int             i_pid;
    int             i_stream_type;
    int             i_stream_id;
    int             i_continuity_counter;
166

167 168 169 170
    /* to be used for carriege of DIV3 */
    vlc_fourcc_t    i_bih_codec;
    int             i_bih_width, i_bih_height;

171 172 173
    /* Specific to mpeg4 in mpeg2ts */
    int             i_es_id;

174
    int             i_decoder_specific_info;
175
    uint8_t         *p_decoder_specific_info;
176

177 178 179
    /* language is iso639-2T */
    uint8_t         lang[3];

180 181 182 183
    sout_buffer_chain_t chain_pes;
    mtime_t             i_pes_dts;
    mtime_t             i_pes_length;
    int                 i_pes_used;
184
    vlc_bool_t          b_key_frame;
185

186 187
} ts_stream_t;

188
struct sout_mux_sys_t
189 190
{
    int             i_pcr_pid;
191 192
    sout_input_t    *p_pcr_input;

193 194 195
    int             i_audio_bound;
    int             i_video_bound;

Christophe Massiot's avatar
Christophe Massiot committed
196 197
    int             i_pid_video;
    int             i_pid_audio;
198 199 200 201 202 203 204 205
    int             i_pid_free; // first usable pid

    int             i_pat_version_number;
    ts_stream_t     pat;

    int             i_pmt_version_number;
    ts_stream_t     pmt;        // Up to now only one program

206 207
    int             i_mpeg4_streams;

208
    int             i_null_continuity_counter;  /* Needed ? */
209

210 211 212
    /* for TS building */
    int64_t             i_bitrate_min;
    int64_t             i_bitrate_max;
213

214
    int64_t             i_shaping_delay;
215
    int64_t             i_pcr_delay;
Laurent Aimar's avatar
Laurent Aimar committed
216

217 218
    int64_t             i_dts_delay;

219 220
    vlc_bool_t          b_use_key_frames;

221
    mtime_t             i_pcr;  /* last PCR emited */
222 223

    csa_t               *csa;
224
    vlc_bool_t          b_crypt_audio;
225
};
226 227


228
/* Reserve a pid and return it */
Christophe Massiot's avatar
Christophe Massiot committed
229
static int  AllocatePID( sout_mux_sys_t *p_sys, int i_cat )
230
{
Christophe Massiot's avatar
Christophe Massiot committed
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
    int i_pid;
    if ( i_cat == VIDEO_ES && p_sys->i_pid_video )
    {
        i_pid = p_sys->i_pid_video;
        p_sys->i_pid_video = 0;
    }
    else if ( i_cat == AUDIO_ES && p_sys->i_pid_audio )
    {
        i_pid = p_sys->i_pid_audio;
        p_sys->i_pid_audio = 0;
    }
    else
    {
        i_pid = ++p_sys->i_pid_free;
    }
    return i_pid;
247 248
}

249 250 251 252 253 254 255 256 257 258 259 260
/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
static int     Capability(sout_mux_t *, int, void *, void * );
static int     AddStream( sout_mux_t *, sout_input_t * );
static int     DelStream( sout_mux_t *, sout_input_t * );
static int     Mux      ( sout_mux_t * );

static void TSSchedule  ( sout_mux_t *p_mux, sout_buffer_chain_t *p_chain_ts,
                          mtime_t i_pcr_length, mtime_t i_pcr_dts );
static void TSDate      ( sout_mux_t *p_mux, sout_buffer_chain_t *p_chain_ts,
                          mtime_t i_pcr_length, mtime_t i_pcr_dts );
261 262
static void GetPAT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c );
263

264 265
static block_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream, vlc_bool_t b_pcr );
static void TSSetPCR( block_t *p_ts, mtime_t i_dts );
266

267
static void PEStoTS  ( sout_instance_t *, sout_buffer_chain_t *, block_t *, ts_stream_t * );
268

269 270 271 272 273
/*****************************************************************************
 * Open:
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
274 275
    sout_mux_t          *p_mux =(sout_mux_t*)p_this;
    sout_mux_sys_t      *p_sys;
276
    char                *val;
277

278
    msg_Dbg( p_mux, "Open" );
279

280
    p_sys = malloc( sizeof( sout_mux_sys_t ) );
281

282 283 284 285 286
    p_mux->pf_capacity  = Capability;
    p_mux->pf_addstream = AddStream;
    p_mux->pf_delstream = DelStream;
    p_mux->pf_mux       = Mux;
    p_mux->p_sys        = p_sys;
287

288 289
    srand( (uint32_t)mdate() );

290 291
    p_sys->i_audio_bound = 0;
    p_sys->i_video_bound = 0;
292

293 294 295
    p_sys->i_pat_version_number = rand() % 32;
    p_sys->pat.i_pid = 0;
    p_sys->pat.i_continuity_counter = 0;
296

297
    p_sys->i_pmt_version_number = rand() % 32;
298
    p_sys->pmt.i_pid = 0x42;
299
    p_sys->pmt.i_continuity_counter = 0;
300

301
    p_sys->i_pid_free = 0x43;
302

Christophe Massiot's avatar
Christophe Massiot committed
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
    p_sys->i_pid_video = 0;
    if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-video" ) ) )
    {
        p_sys->i_pid_video = strtol( val, NULL, 0 );
        if ( p_sys->i_pid_video > p_sys->i_pid_free )
        {
            p_sys->i_pid_free = p_sys->i_pid_video + 1;
        }
    }
    p_sys->i_pid_audio = 0;
    if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-audio" ) ) )
    {
        p_sys->i_pid_audio = strtol( val, NULL, 0 );
        if ( p_sys->i_pid_audio > p_sys->i_pid_free )
        {
            p_sys->i_pid_free = p_sys->i_pid_audio + 1;
        }
    }

322
    p_sys->i_pcr_pid = 0x1fff;
323
    p_sys->p_pcr_input = NULL;
324

325
    p_sys->i_mpeg4_streams = 0;
326

327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
    p_sys->i_null_continuity_counter = 0;

    /* Allow to create constrained stream */
    p_sys->i_bitrate_min = 0;
    p_sys->i_bitrate_max = 0;
    if( ( val = sout_cfg_find_value( p_mux->p_cfg, "bmin" ) ) )
    {
        p_sys->i_bitrate_min = atoll( val );
    }
    if( ( val = sout_cfg_find_value( p_mux->p_cfg, "bmax" ) ) )
    {
        p_sys->i_bitrate_max = atoll( val );
    }
    if( p_sys->i_bitrate_min > 0 && p_sys->i_bitrate_max > 0 &&
        p_sys->i_bitrate_min > p_sys->i_bitrate_max )
    {
gbazin's avatar
 
gbazin committed
343 344
        msg_Err( p_mux, "incompatible minimum and maximum bitrate, "
                 "disabling bitrate control" );
345 346 347
        p_sys->i_bitrate_min = 0;
        p_sys->i_bitrate_max = 0;
    }
348
    if( p_sys->i_bitrate_min > 0 || p_sys->i_bitrate_max > 0 )
349
    {
350 351 352
        msg_Err( p_mux, "bmin and bmax no more supported (if you need them report it)" );
    }

353 354
    p_sys->i_shaping_delay = 200000;
    if( ( val = sout_cfg_find_value( p_mux->p_cfg, "shaping" ) ) )
355
    {
356 357
        p_sys->i_shaping_delay = (int64_t)atoi( val ) * 1000;
        if( p_sys->i_shaping_delay <= 0 )
358 359
        {
            msg_Err( p_mux,
360 361 362
                     "invalid shaping ("I64Fd"ms) reseting to 200ms",
                     p_sys->i_shaping_delay / 1000 );
            p_sys->i_shaping_delay = 200000;
363 364
        }
    }
365 366
    p_sys->i_pcr_delay = 30000;
    if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pcr" ) ) )
367
    {
368 369
        p_sys->i_pcr_delay = (int64_t)atoi( val ) * 1000;
        if( p_sys->i_pcr_delay <= 0 ||
370
            p_sys->i_pcr_delay >= p_sys->i_shaping_delay )
371 372
        {
            msg_Err( p_mux,
373 374 375
                     "invalid pcr delay ("I64Fd"ms) reseting to 30ms",
                     p_sys->i_pcr_delay / 1000 );
            p_sys->i_pcr_delay = 30000;
376 377
        }
    }
378
    p_sys->b_use_key_frames = VLC_FALSE;
379 380
    if( sout_cfg_find( p_mux->p_cfg, "use-key-frames" ) )
    {
381
        p_sys->b_use_key_frames = VLC_TRUE;
382
    }
gbazin's avatar
 
gbazin committed
383

384 385 386 387 388 389
    p_sys->i_dts_delay = 200000;
    if( ( val = sout_cfg_find_value( p_mux->p_cfg, "dts-delay" ) ) )
    {
        p_sys->i_dts_delay = (int64_t)atoi( val ) * 1000;
    }

390 391 392
    msg_Dbg( p_mux, "shaping="I64Fd" pcr="I64Fd" dts_delay="I64Fd,
             p_sys->i_shaping_delay, p_sys->i_pcr_delay, p_sys->i_dts_delay );

Christophe Massiot's avatar
Christophe Massiot committed
393
    /* for TS generation */
394
    p_sys->i_pcr    = 0;
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409

    p_sys->csa      = NULL;
    if( ( val = sout_cfg_find_value( p_mux->p_cfg, "csa-ck" ) ) )
    {
        /* skip 0x */
        if( val[0] == '0' && ( val[1] == 'x' || val[1] == 'X' ) )
        {
            val += 2;
        }
        if( strlen( val ) != 16 )
        {
            msg_Dbg( p_mux, "invalid csa ck (it must be 16 chars long)" );
        }
        else
        {
410
            uint64_t i_ck = strtoll( val, NULL, 16 );
gbazin's avatar
gbazin committed
411 412 413
            uint8_t  ck[8];
            int      i;

414 415 416 417 418 419 420 421 422 423 424 425
            for( i = 0; i < 8; i++ )
            {
                ck[i] = ( i_ck >> ( 56 - 8*i) )&0xff;
            }

            msg_Dbg( p_mux, "using CSA scrambling with ck=%x:%x:%x:%x:%x:%x:%x:%x",
                     ck[0], ck[1], ck[2], ck[3], ck[4], ck[5], ck[6], ck[7] );

            p_sys->csa = csa_New();
            csa_SetCW( p_sys->csa, ck, ck );
        }
    }
426 427 428 429 430 431
    p_sys->b_crypt_audio = VLC_TRUE;
    if( sout_cfg_find( p_mux->p_cfg, "no-crypt-audio" ) )
    {
        p_sys->b_crypt_audio = VLC_FALSE;
    }

432 433 434 435 436 437 438 439
    return VLC_SUCCESS;
}

/*****************************************************************************
 * Close:
 *****************************************************************************/
static void Close( vlc_object_t * p_this )
{
440 441
    sout_mux_t          *p_mux = (sout_mux_t*)p_this;
    sout_mux_sys_t      *p_sys = p_mux->p_sys;
442

443
    msg_Dbg( p_mux, "Close" );
444 445 446 447
    if( p_sys->csa )
    {
        csa_Delete( p_sys->csa );
    }
448

449
    free( p_sys );
450 451
}

452 453 454
/*****************************************************************************
 * Capability:
 *****************************************************************************/
455
static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer )
456 457 458 459 460 461 462 463 464 465
{
   switch( i_query )
   {
        case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
            *(vlc_bool_t*)p_answer = VLC_TRUE;
            return( SOUT_MUX_CAP_ERR_OK );
        default:
            return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
   }
}
466

467 468 469
/*****************************************************************************
 * AddStream: called for each stream addition
 *****************************************************************************/
470
static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
471
{
472
    sout_mux_sys_t      *p_sys = p_mux->p_sys;
473 474
    ts_stream_t         *p_stream;

475
    p_input->p_sys = (void*)p_stream = malloc( sizeof( ts_stream_t ) );
476

477
    /* Init this new stream */
Christophe Massiot's avatar
Christophe Massiot committed
478
    p_stream->i_pid = AllocatePID( p_sys, p_input->p_fmt->i_cat );
479 480 481
    p_stream->i_continuity_counter    = 0;
    p_stream->i_decoder_specific_info = 0;
    p_stream->p_decoder_specific_info = NULL;
482

483 484
    msg_Dbg( p_mux, "adding input codec=%4.4s pid=%d", (char*)&p_input->p_fmt->i_codec, p_stream->i_pid );

485
    /* All others fields depand on codec */
486
    switch( p_input->p_fmt->i_cat )
487 488
    {
        case VIDEO_ES:
489
            switch( p_input->p_fmt->i_codec )
490 491
            {
                case VLC_FOURCC( 'm', 'p','g', 'v' ):
492
                    /* TODO: do we need to check MPEG-I/II ? */
493
                    p_stream->i_stream_type = 0x02;
494
                    p_stream->i_stream_id = 0xe0;
495 496 497 498
                    break;
                case VLC_FOURCC( 'm', 'p','4', 'v' ):
                    p_stream->i_stream_type = 0x10;
                    p_stream->i_stream_id = 0xfa;
499
                    p_sys->i_mpeg4_streams++;
500
                    p_stream->i_es_id = p_stream->i_pid;
501
                    break;
502 503 504 505
                /* XXX dirty dirty but somebody want that : using crapy MS-codec XXX */
                /* I didn't want to do that :P */
                case VLC_FOURCC( 'H', '2', '6', '3' ):
                case VLC_FOURCC( 'I', '2', '6', '3' ):
506
                case VLC_FOURCC( 'W', 'M', 'V', '2' ):
507 508 509 510
                case VLC_FOURCC( 'W', 'M', 'V', '1' ):
                case VLC_FOURCC( 'D', 'I', 'V', '3' ):
                case VLC_FOURCC( 'D', 'I', 'V', '2' ):
                case VLC_FOURCC( 'D', 'I', 'V', '1' ):
511
                case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
512 513
                    p_stream->i_stream_type = 0xa0; // private
                    p_stream->i_stream_id = 0xa0;   // beurk
514 515 516
                    p_stream->i_bih_codec  = p_input->p_fmt->i_codec;
                    p_stream->i_bih_width  = p_input->p_fmt->video.i_width;
                    p_stream->i_bih_height = p_input->p_fmt->video.i_height;
517
                    break;
518
                default:
519 520
                    free( p_stream );
                    return VLC_EGENERIC;
521
            }
522
            p_sys->i_video_bound++;
523
            break;
524

525
        case AUDIO_ES:
526
            switch( p_input->p_fmt->i_codec )
527
            {
528
                case VLC_FOURCC( 'm', 'p','g', 'a' ):
529
                    p_stream->i_stream_type = p_input->p_fmt->audio.i_rate >= 32000 ? 0x03 : 0x04;
530
                    p_stream->i_stream_id = 0xc0;
531
                    break;
532 533
                case VLC_FOURCC( 'a', '5','2', ' ' ):
                    p_stream->i_stream_type = 0x81;
534
                    p_stream->i_stream_id = 0xbd;
535
                    break;
536 537 538 539 540 541 542 543 544
                case VLC_FOURCC( 'l', 'p','c', 'm' ):
                    p_stream->i_stream_type = 0x83;
                    p_stream->i_stream_id = 0xbd;
                    break;
                case VLC_FOURCC( 'd', 't','s', ' ' ):
                    p_stream->i_stream_type = 0x85;
                    p_stream->i_stream_id = 0xbd;
                    break;

545 546 547
                case VLC_FOURCC( 'm', 'p','4', 'a' ):
                    p_stream->i_stream_type = 0x11;
                    p_stream->i_stream_id = 0xfa;
548
                    p_sys->i_mpeg4_streams++;
549
                    p_stream->i_es_id = p_stream->i_pid;
550 551
                    break;
                default:
552 553
                    free( p_stream );
                    return VLC_EGENERIC;
554
            }
555
            p_sys->i_audio_bound++;
556
            break;
557

558
        case SPU_ES:
559
            switch( p_input->p_fmt->i_codec )
560
            {
561 562
                case VLC_FOURCC( 's', 'p','u', ' ' ):
                    p_stream->i_stream_type = 0x82;
563
                    p_stream->i_stream_id = 0xbd;
564 565 566 567
                    break;
                default:
                    free( p_stream );
                    return VLC_EGENERIC;
568
            }
569
            break;
570

571
        default:
572 573
            free( p_stream );
            return VLC_EGENERIC;
574 575
    }

576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
    p_stream->lang[0] =
    p_stream->lang[1] =
    p_stream->lang[2] = '\0';
    if( p_input->p_fmt->psz_language )
    {
        char *psz = p_input->p_fmt->psz_language;
        const iso639_lang_t *pl = NULL;

        if( strlen( psz ) == 2 )
        {
            pl = GetLang_1( psz );
        }
        else if( strlen( psz ) == 3 )
        {
            pl = GetLang_2B( psz );
            if( !strcmp( pl->psz_iso639_1, "??" ) )
            {
                pl = GetLang_2T( psz );
            }
        }
        if( pl && strcmp( pl->psz_iso639_1, "??" ) )
        {
            p_stream->lang[0] = pl->psz_iso639_2T[0];
            p_stream->lang[1] = pl->psz_iso639_2T[1];
            p_stream->lang[2] = pl->psz_iso639_2T[2];

            msg_Dbg( p_mux, "    - lang=%c%c%c",
                     p_stream->lang[0],
                     p_stream->lang[1],
                     p_stream->lang[2] );
        }
    }


610
    /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
611
    p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra;
612 613 614 615 616
    if( p_stream->i_decoder_specific_info > 0 )
    {
        p_stream->p_decoder_specific_info =
            malloc( p_stream->i_decoder_specific_info );
        memcpy( p_stream->p_decoder_specific_info,
617 618
                p_input->p_fmt->p_extra,
                p_input->p_fmt->i_extra );
619
    }
620 621 622 623 624 625

    /* Init pes chain */
    BufferChainInit( &p_stream->chain_pes );
    p_stream->i_pes_dts    = 0;
    p_stream->i_pes_length = 0;
    p_stream->i_pes_used   = 0;
626
    p_stream->b_key_frame  = 0;
627 628 629 630 631 632 633 634 635 636 637

    /* We only change PMT version (PAT isn't changed) */
    p_sys->i_pmt_version_number = ( p_sys->i_pmt_version_number + 1 )%32;

    /* Update pcr_pid */
    if( p_input->p_fmt->i_cat != SPU_ES &&
        ( p_sys->i_pcr_pid == 0x1fff || p_input->p_fmt->i_cat == VIDEO_ES ) )
    {
        if( p_sys->p_pcr_input )
        {
            /* There was already a PCR stream, so clean context */
638
            /* FIXME */
639 640 641
        }
        p_sys->i_pcr_pid   = p_stream->i_pid;
        p_sys->p_pcr_input = p_input;
642 643

        msg_Dbg( p_mux, "new PCR PID is %d", p_sys->i_pcr_pid );
644 645 646
    }

    return VLC_SUCCESS;
647 648
}

649 650 651
/*****************************************************************************
 * DelStream: called before a stream deletion
 *****************************************************************************/
652
static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
653
{
654 655
    sout_mux_sys_t  *p_sys = p_mux->p_sys;
    ts_stream_t     *p_stream;
656
    char            *val;
657

658
    p_stream = (ts_stream_t*)p_input->p_sys;
659
    msg_Dbg( p_mux, "removing input pid=%d", p_stream->i_pid );
660

661 662 663 664 665 666
    if( p_sys->i_pcr_pid == p_stream->i_pid )
    {
        int i;

        /* Find a new pcr stream (Prefer Video Stream) */
        p_sys->i_pcr_pid = 0x1fff;
667
        p_sys->p_pcr_input = NULL;
668 669 670 671 672 673 674 675 676
        for( i = 0; i < p_mux->i_nb_inputs; i++ )
        {
            if( p_mux->pp_inputs[i] == p_input )
            {
                continue;
            }

            if( p_mux->pp_inputs[i]->p_fmt->i_cat == VIDEO_ES )
            {
677 678
                p_sys->i_pcr_pid  =
                    ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
679 680 681
                p_sys->p_pcr_input= p_mux->pp_inputs[i];
                break;
            }
682 683
            else if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES &&
                     p_sys->i_pcr_pid == 0x1fff )
684
            {
685 686
                p_sys->i_pcr_pid  =
                    ((ts_stream_t*)p_mux->pp_inputs[i]->p_sys)->i_pid;
687 688 689 690 691 692
                p_sys->p_pcr_input= p_mux->pp_inputs[i];
            }
        }
        if( p_sys->p_pcr_input )
        {
            /* Empty TS buffer */
693
            /* FIXME */
694
        }
695
        msg_Dbg( p_mux, "new PCR PID is %d", p_sys->i_pcr_pid );
696 697
    }

698 699 700
    /* Empty all data in chain_pes */
    BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );

701 702 703 704 705 706
    if( p_stream->p_decoder_specific_info )
    {
        free( p_stream->p_decoder_specific_info );
    }
    if( p_stream->i_stream_id == 0xfa || p_stream->i_stream_id == 0xfb )
    {
707
        p_sys->i_mpeg4_streams--;
708
    }
709 710 711 712 713 714
    if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-video" ) ) )
    {
        int i_pid_video = strtol( val, NULL, 0 );
        if ( i_pid_video == p_stream->i_pid )
        {
            p_sys->i_pid_video = i_pid_video;
715
            msg_Dbg( p_mux, "freeing video PID %d", i_pid_video );
716 717 718 719 720 721 722 723
        }
    }
    if( ( val = sout_cfg_find_value( p_mux->p_cfg, "pid-audio" ) ) )
    {
        int i_pid_audio = strtol( val, NULL, 0 );
        if ( i_pid_audio == p_stream->i_pid )
        {
            p_sys->i_pid_audio = i_pid_audio;
724
            msg_Dbg( p_mux, "freeing audio PID %d", i_pid_audio );
725 726
        }
    }
Laurent Aimar's avatar
Laurent Aimar committed
727 728
    free( p_stream );

729
    /* We only change PMT version (PAT isn't changed) */
730
    p_sys->i_pmt_version_number++; p_sys->i_pmt_version_number %= 32;
731

732
    return VLC_SUCCESS;
733 734
}

735 736 737 738 739 740 741 742
/*****************************************************************************
 * Mux: Call each time there is new data for at least one stream
 *****************************************************************************
 *
 *****************************************************************************/
static int Mux( sout_mux_t *p_mux )
{
    sout_mux_sys_t  *p_sys = p_mux->p_sys;
743
    ts_stream_t     *p_pcr_stream;
744

745 746
    if( p_sys->i_pcr_pid == 0x1fff )
    {
747
        msg_Dbg( p_mux, "waiting for PCR streams" );
748 749 750
        msleep( 1000 );
        return VLC_SUCCESS;
    }
751
    p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
752

753
    for( ;; )
754
    {
755 756 757 758 759
        sout_buffer_chain_t chain_ts;
        int                 i_packet_count;
        int                 i_packet_pos;
        mtime_t             i_pcr_dts;
        mtime_t             i_pcr_length;
760
        mtime_t             i_shaping_delay;
761
        int i;
762

763 764 765 766 767 768 769 770 771
        if( p_pcr_stream->b_key_frame )
        {
            i_shaping_delay = p_pcr_stream->i_pes_length;
        }
        else
        {
            i_shaping_delay = p_sys->i_shaping_delay;
        }

772 773
        /* 1: get enough PES packet for all input */
        for( ;; )
774
        {
775
            vlc_bool_t b_ok = VLC_TRUE;
776
            block_t *p_data;
777

778
            /* Accumulate enough data in the pcr stream (>i_shaping_delay) */
779 780 781 782 783 784
            /* Accumulate enough data in all other stream ( >= length of pcr) */
            for( i = 0; i < p_mux->i_nb_inputs; i++ )
            {
                sout_input_t *p_input = p_mux->pp_inputs[i];
                ts_stream_t *p_stream = (ts_stream_t*)p_input->p_sys;

785 786 787 788
                if( ( p_stream == p_pcr_stream
                            && p_stream->i_pes_length < i_shaping_delay ) ||
                    p_stream->i_pes_dts + p_stream->i_pes_length 
                        < p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
                {
                    /* Need more data */
                    if( p_input->p_fifo->i_depth <= 1 )
                    {
                        if( p_input->p_fmt->i_cat == AUDIO_ES ||
                            p_input->p_fmt->i_cat == VIDEO_ES )
                        {
                            /* We need more data */
                            return VLC_SUCCESS;
                        }
                        else if( p_input->p_fifo->i_depth <= 0 )
                        {
                            /* spu, only one packet is needed */
                            continue;
                        }
                    }
                    b_ok = VLC_FALSE;

807
                    p_data = block_FifoGet( p_input->p_fifo );
Laurent Aimar's avatar
Laurent Aimar committed
808 809
                    if( p_input->p_fifo->i_depth > 0 )
                    {
810
                        block_t *p_next = block_FifoShow( p_input->p_fifo );
Laurent Aimar's avatar
Laurent Aimar committed
811 812 813

                        p_data->i_length = p_next->i_dts - p_data->i_dts;
                    }
814 815 816 817 818 819 820 821 822

                    if( ( p_pcr_stream->i_pes_dts > 0 && p_data->i_dts - 2000000 > p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length ) ||
                        p_data->i_dts < p_stream->i_pes_dts ||
                        ( p_stream->i_pes_dts > 0 && p_data->i_dts - 2000000 > p_stream->i_pes_dts + p_stream->i_pes_length ) )
                    {
                        msg_Warn( p_mux, "packet with too strange dts (dts=%lld,old=%lld,pcr=%lld)",
                                  p_data->i_dts,
                                  p_stream->i_pes_dts,
                                  p_pcr_stream->i_pes_dts );
823
                        block_Release( p_data );
824 825 826 827 828 829 830 831 832 833 834 835 836 837

                        BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
                        p_stream->i_pes_dts = 0;
                        p_stream->i_pes_used = 0;
                        p_stream->i_pes_length = 0;

                        BufferChainClean( p_mux->p_sout, &p_pcr_stream->chain_pes );
                        p_pcr_stream->i_pes_dts = 0;
                        p_pcr_stream->i_pes_used = 0;
                        p_pcr_stream->i_pes_length = 0;

                    }
                    else
                    {
838 839 840 841 842 843
                        if( p_data->i_length < 0 || p_data->i_length > 2000000 )
                        {
                            /* FIXME choose a better value, but anyway we should never
                             * have to do that */
                            p_data->i_length = 1000;
                        }
844 845 846 847 848 849 850
                        p_stream->i_pes_length += p_data->i_length;
                        if( p_stream->i_pes_dts == 0 )
                        {
                            p_stream->i_pes_dts = p_data->i_dts;
                        }

                        /* Convert to pes */
851 852 853 854 855
                        if( p_stream->i_stream_id == 0xa0 && p_data->i_pts <= 0 )
                        {
                            /* XXX yes I know, it's awfull, but it's needed, so don't remove it ... */
                            p_data->i_pts = p_data->i_dts;
                        }
856 857 858
                        E_( EStoPES )( p_mux->p_sout, &p_data, p_data, p_stream->i_stream_id, 1 );

                        BufferChainAppend( &p_stream->chain_pes, p_data );
859 860

                        if( p_sys->b_use_key_frames && p_stream == p_pcr_stream
861
                            && (p_data->i_flags & BLOCK_FLAG_TYPE_I )
862 863 864 865 866
                            && (p_stream->i_pes_length > 300000) )
                        {
                            i_shaping_delay = p_stream->i_pes_length;
                            p_stream->b_key_frame = 1;
                        }
867 868 869 870 871 872 873 874
                    }
                }
            }

            if( b_ok )
            {
                break;
            }
875
        }
876

877 878 879
        /* save */
        i_pcr_dts      = p_pcr_stream->i_pes_dts;
        i_pcr_length   = p_pcr_stream->i_pes_length;
880
        p_pcr_stream->b_key_frame = 0;
881 882 883 884 885

        /* msg_Dbg( p_mux, "starting muxing %lldms", i_pcr_length / 1000 ); */
        /* 2: calculate non accurate total size of muxed ts */
        i_packet_count = 0;
        for( i = 0; i < p_mux->i_nb_inputs; i++ )
886
        {
887
            ts_stream_t *p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;
888
            block_t *p_pes;
889

890
            /* False for pcr stream but it will be enough to do PCR algo */
891 892
            for( p_pes = p_stream->chain_pes.p_first; p_pes != NULL; p_pes = p_pes->p_next )
            {
893
                int i_size = p_pes->i_buffer;
894 895 896 897 898 899 900 901
                if( p_pes->i_dts + p_pes->i_length > p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length )
                {
                    mtime_t i_frag = p_pcr_stream->i_pes_dts + p_pcr_stream->i_pes_length - p_pes->i_dts;
                    if( i_frag < 0 )
                    {
                        /* Next stream */
                        break;
                    }
902
                    i_size = p_pes->i_buffer * i_frag / p_pes->i_length;
903 904 905
                }
                i_packet_count += ( i_size + 183 ) / 184;
            }
906
        }
907 908 909 910 911 912 913 914 915 916 917 918
        /* add overhead for PCR (not really exact) */
        i_packet_count += ( 8 * i_pcr_length / p_sys->i_pcr_delay + 175 ) / 176;


        /* 3: mux PES into TS */
        BufferChainInit( &chain_ts );
        /* append PAT/PMT  -> FIXME with big pcr delay it won't have enough pat/pmt */
        GetPAT( p_mux, &chain_ts);
        GetPMT( p_mux, &chain_ts );
        i_packet_pos = 0;
        i_packet_count += chain_ts.i_depth;
        /* msg_Dbg( p_mux, "estimated pck=%d", i_packet_count ); */
919

920
        for( ;; )
921
        {
922 923 924
            int         i_stream;
            mtime_t     i_dts;
            ts_stream_t *p_stream;
925
            sout_input_t *p_input;
926
            block_t *p_ts;
927
            vlc_bool_t   b_pcr;
928

929
            /* Select stream (lowest dts) */
930
            for( i = 0, i_stream = -1, i_dts = 0; i < p_mux->i_nb_inputs; i++ )
931
            {
932
                p_input = p_mux->pp_inputs[i];
933 934 935
                p_stream = (ts_stream_t*)p_mux->pp_inputs[i]->p_sys;

                if( p_stream->i_pes_dts == 0 )
936
                {
937
                    continue;
938
                }
939 940 941

                if( i_stream == -1 ||
                    p_stream->i_pes_dts < i_dts )
942
                {
943 944
                    i_stream = i;
                    i_dts = p_stream->i_pes_dts;
945 946
                }
            }
947 948 949 950 951
            if( i_stream == -1 )
            {
                break;
            }
            p_stream = (ts_stream_t*)p_mux->pp_inputs[i_stream]->p_sys;
952

953