]> git.sesse.net Git - vlc/blobdiff - modules/mux/mpeg/ts.c
Use var_CreateGet* when applicable.
[vlc] / modules / mux / mpeg / ts.c
index 202648c90e07fd00a87e12d96adabdd5a177470b..cc61ca8ba5a844a6d2d430af5230ebc4110c5174 100644 (file)
 # include "config.h"
 #endif
 
-#include <vlc/vlc.h>
+#include <limits.h>
+
+#include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_sout.h>
 #include <vlc_codecs.h>
 #include <vlc_block.h>
 
-#include "iso_lang.h"
+#include <vlc_iso_lang.h>
 
 #include "bits.h"
 #include "pes.h"
  *    if they arrive a bit late
  *    (We cannot rely on the fact that the fifo should be full)
  */
+
+/*****************************************************************************
+ * Callback prototypes
+ *****************************************************************************/
+static int ChangeKeyCallback    ( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * );
+static int ActiveKeyCallback    ( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * );
+
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
@@ -134,7 +143,7 @@ static void    Close  ( vlc_object_t * );
   "of the shaping algorithm, since I frames are usually the biggest " \
   "frames in the stream.")
 
-#define PCR_TEXT N_("PCR delay (ms)")
+#define PCR_TEXT N_("PCR interval (ms)")
 #define PCR_LONGTEXT N_("Set at which interval " \
   "PCRs (Program Clock Reference) will be sent (in milliseconds). " \
   "This value should be below 100ms. (default is 70ms).")
@@ -160,85 +169,93 @@ static void    Close  ( vlc_object_t * );
 #define CK_LONGTEXT N_("CSA encryption key. This must be a " \
   "16 char string (8 hexadecimal bytes).")
 
+#define CK2_TEXT N_("Second CSA Key")
+#define CK2_LONGTEXT N_("The even CSA encryption key. This must be a " \
+  "16 char string (8 hexadecimal bytes).")
+
+#define CU_TEXT N_("CSA Key in use")
+#define CU_LONGTEXT N_("CSA encryption key used. It can be the odd/first/1 " \
+  "(default) or the even/second/2 one.")
+
 #define CPKT_TEXT N_("Packet size in bytes to encrypt")
 #define CPKT_LONGTEXT N_("Size of the TS packet to encrypt. " \
     "The encryption routines subtract the TS-header from the value before " \
     "encrypting." )
 
 #define SOUT_CFG_PREFIX "sout-ts-"
-#ifdef HAVE_BSEARCH
-#   define MAX_PMT 64       /* Maximum number of programs. FIXME: I just chose an arbitary number. Where is the maximum in the spec? */
-#else
-#   define MAX_PMT 1
-#endif
+#define MAX_PMT 64       /* Maximum number of programs. FIXME: I just chose an arbitary number. Where is the maximum in the spec? */
 #define MAX_PMT_PID 64       /* Maximum pids in each pmt.  FIXME: I just chose an arbitary number. Where is the maximum in the spec? */
 
-vlc_module_begin();
-    set_description( _("TS muxer (libdvbpsi)") );
-    set_shortname( "MPEG-TS");
-    set_category( CAT_SOUT );
-    set_subcategory( SUBCAT_SOUT_MUX );
-    set_capability( "sout mux", 120 );
-    add_shortcut( "ts" );
+vlc_module_begin ()
+    set_description( N_("TS muxer (libdvbpsi)") )
+    set_shortname( "MPEG-TS")
+    set_category( CAT_SOUT )
+    set_subcategory( SUBCAT_SOUT_MUX )
+    set_capability( "sout mux", 120 )
+    add_shortcut( "ts" )
 
     add_integer( SOUT_CFG_PREFIX "pid-video", 0, NULL,VPID_TEXT, VPID_LONGTEXT,
-                                  true );
+                                  true )
     add_integer( SOUT_CFG_PREFIX "pid-audio", 0, NULL, APID_TEXT,
-                 APID_LONGTEXT, true );
+                 APID_LONGTEXT, true )
     add_integer( SOUT_CFG_PREFIX "pid-spu", 0, NULL, SPUPID_TEXT,
-                 SPUPID_LONGTEXT, true );
+                 SPUPID_LONGTEXT, true )
     add_integer( SOUT_CFG_PREFIX "pid-pmt", 0, NULL, PMTPID_TEXT,
-                 PMTPID_LONGTEXT, true );
+                 PMTPID_LONGTEXT, true )
     add_integer( SOUT_CFG_PREFIX "tsid", 0, NULL, TSID_TEXT,
-                 TSID_LONGTEXT, true );
+                 TSID_LONGTEXT, true )
 #ifdef HAVE_DVBPSI_SDT
     add_integer( SOUT_CFG_PREFIX "netid", 0, NULL, NETID_TEXT,
-                 NETID_LONGTEXT, true );
+                 NETID_LONGTEXT, true )
 #endif
     add_string( SOUT_CFG_PREFIX "program-pmt", NULL, NULL, PMTPROG_TEXT,
-                PMTPROG_LONGTEXT, true );
-    add_bool( SOUT_CFG_PREFIX "es-id-pid", 0, NULL, PID_TEXT, PID_LONGTEXT,
-              true );
-    add_string( SOUT_CFG_PREFIX "muxpmt", NULL, NULL, MUXPMT_TEXT, MUXPMT_LONGTEXT, true );
+                PMTPROG_LONGTEXT, true )
+    add_bool( SOUT_CFG_PREFIX "es-id-pid", false, NULL, PID_TEXT, PID_LONGTEXT,
+              true )
+    add_string( SOUT_CFG_PREFIX "muxpmt", NULL, NULL, MUXPMT_TEXT, MUXPMT_LONGTEXT, true )
 #ifdef HAVE_DVBPSI_SDT
-    add_string( SOUT_CFG_PREFIX "sdtdesc", NULL, NULL, SDTDESC_TEXT, SDTDESC_LONGTEXT, true );
+    add_string( SOUT_CFG_PREFIX "sdtdesc", NULL, NULL, SDTDESC_TEXT, SDTDESC_LONGTEXT, true )
 #endif
     add_bool( SOUT_CFG_PREFIX "alignment", true, NULL, ALIGNMENT_TEXT,
-              ALIGNMENT_LONGTEXT, true );
+              ALIGNMENT_LONGTEXT, true )
 
     add_integer( SOUT_CFG_PREFIX "shaping", 200, NULL, SHAPING_TEXT,
-                 SHAPING_LONGTEXT, true );
+                 SHAPING_LONGTEXT, true )
     add_bool( SOUT_CFG_PREFIX "use-key-frames", false, NULL, KEYF_TEXT,
-              KEYF_LONGTEXT, true );
+              KEYF_LONGTEXT, true )
 
     add_integer( SOUT_CFG_PREFIX "pcr", 70, NULL, PCR_TEXT, PCR_LONGTEXT,
-                 true );
+                 true )
     add_integer( SOUT_CFG_PREFIX "bmin", 0, NULL, BMIN_TEXT, BMIN_LONGTEXT,
-                 true );
+                 true )
     add_integer( SOUT_CFG_PREFIX "bmax", 0, NULL, BMAX_TEXT, BMAX_LONGTEXT,
-                 true );
+                 true )
     add_integer( SOUT_CFG_PREFIX "dts-delay", 400, NULL, DTS_TEXT,
-                 DTS_LONGTEXT, true );
+                 DTS_LONGTEXT, true )
 
     add_bool( SOUT_CFG_PREFIX "crypt-audio", true, NULL, ACRYPT_TEXT,
-              ACRYPT_LONGTEXT, true );
+              ACRYPT_LONGTEXT, true )
     add_bool( SOUT_CFG_PREFIX "crypt-video", true, NULL, VCRYPT_TEXT,
-              VCRYPT_LONGTEXT, true );
+              VCRYPT_LONGTEXT, true )
 
     add_string( SOUT_CFG_PREFIX "csa-ck", NULL, NULL, CK_TEXT, CK_LONGTEXT,
-                true );
-    add_integer( SOUT_CFG_PREFIX "csa-pkt", 188, NULL, CPKT_TEXT, CPKT_LONGTEXT, true );
+                true )
+    add_string( SOUT_CFG_PREFIX "csa2-ck", NULL, NULL, CK2_TEXT, CK2_LONGTEXT,
+                true )
+    add_string( SOUT_CFG_PREFIX "csa-use", "1", NULL, CU_TEXT, CU_LONGTEXT,
+                true )
+    add_integer( SOUT_CFG_PREFIX "csa-pkt", 188, NULL, CPKT_TEXT, CPKT_LONGTEXT, true )
 
-    set_callbacks( Open, Close );
-vlc_module_end();
+    set_callbacks( Open, Close )
+vlc_module_end ()
 
 /*****************************************************************************
  * Local data structures
  *****************************************************************************/
-static const char *ppsz_sout_options[] = {
+static const char *const ppsz_sout_options[] = {
     "pid-video", "pid-audio", "pid-spu", "pid-pmt", "tsid", "netid",
     "es-id-pid", "shaping", "pcr", "bmin", "bmax", "use-key-frames",
-    "dts-delay", "csa-ck", "csa-pkt", "crypt-audio", "crypt-video",
+    "dts-delay", "csa-ck", "csa2-ck", "csa-use", "csa-pkt", "crypt-audio", "crypt-video",
     "muxpmt", "sdtdesc", "program-pmt", "alignment",
     NULL
 };
@@ -356,6 +373,8 @@ struct sout_mux_sys_t
     int             i_pcr_pid;
     sout_input_t    *p_pcr_input;
 
+    vlc_mutex_t     csa_lock;
+
     int             i_audio_bound;
     int             i_video_bound;
 
@@ -493,6 +512,8 @@ static int Open( vlc_object_t *p_this )
     p_sys->dvbpmt = NULL;
     memset( &p_sys->pmtmap, 0, sizeof(p_sys->pmtmap) );
 
+    vlc_mutex_init( &p_sys->csa_lock );
+
     p_mux->pf_control   = Control;
     p_mux->pf_addstream = AddStream;
     p_mux->pf_delstream = DelStream;
@@ -508,8 +529,7 @@ static int Open( vlc_object_t *p_this )
     p_sys->i_audio_bound = 0;
     p_sys->i_video_bound = 0;
 
-    var_Get( p_mux, SOUT_CFG_PREFIX "es-id-pid", &val );
-    p_sys->b_es_id_pid = val.b_bool;
+    p_sys->b_es_id_pid = var_GetBool( p_mux, SOUT_CFG_PREFIX "es-id-pid" );
 
     var_Get( p_mux, SOUT_CFG_PREFIX "muxpmt", &val );
     /*
@@ -768,52 +788,62 @@ static int Open( vlc_object_t *p_this )
     p_sys->i_pcr    = 0;
 
     p_sys->csa      = NULL;
+    var_Create( p_mux, SOUT_CFG_PREFIX "csa-ck", VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
     var_Get( p_mux, SOUT_CFG_PREFIX "csa-ck", &val );
     if( val.psz_string && *val.psz_string )
     {
-        char *psz = val.psz_string;
+        int i_res;
+        vlc_value_t csa2;
 
-        /* skip 0x */
-        if( psz[0] == '0' && ( psz[1] == 'x' || psz[1] == 'X' ) )
+        p_sys->csa = csa_New();
+
+        var_Create( p_mux, SOUT_CFG_PREFIX "csa2-ck", VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
+        var_Get( p_mux, SOUT_CFG_PREFIX "csa2-ck", &csa2 );
+        i_res = csa_SetCW( (vlc_object_t*)p_mux, p_sys->csa, val.psz_string, true );
+        if( i_res == VLC_SUCCESS && csa2.psz_string && *csa2.psz_string )
         {
-            psz += 2;
+            if( csa_SetCW( (vlc_object_t*)p_mux, p_sys->csa, csa2.psz_string, false ) != VLC_SUCCESS )
+            {
+                csa_SetCW( (vlc_object_t*)p_mux, p_sys->csa, val.psz_string, false );
+            }
         }
-        if( strlen( psz ) != 16 )
+        else if( i_res == VLC_SUCCESS )
         {
-            msg_Dbg( p_mux, "invalid csa ck (it must be 16 chars long)" );
+            csa_SetCW( (vlc_object_t*)p_mux, p_sys->csa, val.psz_string, false );
         }
         else
         {
-            uint64_t i_ck = strtoull( psz, NULL, 16 );
-            uint8_t  ck[8];
-            int      i;
+            csa_Delete( p_sys->csa );
+            p_sys->csa = NULL;
+        }
 
-            for( i = 0; i < 8; i++ )
+        if( p_sys->csa )
+        {
+            vlc_value_t use_val, pkt_val;
+
+            var_Create( p_mux, SOUT_CFG_PREFIX "csa-use", VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
+            var_Get( p_mux, SOUT_CFG_PREFIX "csa-use", &use_val );
+            var_AddCallback( p_mux, SOUT_CFG_PREFIX "csa-use", ActiveKeyCallback, NULL );
+            var_AddCallback( p_mux, SOUT_CFG_PREFIX "csa-ck", ChangeKeyCallback, (void *)1 );
+            var_AddCallback( p_mux, SOUT_CFG_PREFIX "csa2-ck", ChangeKeyCallback, NULL );
+
+            if ( var_Set( p_mux, SOUT_CFG_PREFIX "csa-use", use_val ) != VLC_SUCCESS )
             {
-                ck[i] = ( i_ck >> ( 56 - 8*i) )&0xff;
+                var_SetString( p_mux, SOUT_CFG_PREFIX "csa-use", "odd" );
             }
-#ifndef TS_NO_CSA_CK_MSG
-            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] );
-#endif
-            p_sys->csa = csa_New();
-            if( p_sys->csa )
-            {
-                vlc_value_t pkt_val;
-
-                csa_SetCW( p_sys->csa, ck, ck );
+            free( use_val.psz_string );
 
-                var_Get( p_mux, SOUT_CFG_PREFIX "csa-pkt", &pkt_val );
-                if( pkt_val.i_int < 12 || pkt_val.i_int > 188 )
-                {
-                    msg_Err( p_mux, "wrong packet size %d specified.", pkt_val.i_int );
-                    msg_Warn( p_mux, "using default packet size of 188 bytes" );
-                    p_sys->i_csa_pkt_size = 188;
-                }
-                else p_sys->i_csa_pkt_size = pkt_val.i_int;
-                msg_Dbg( p_mux, "encrypting %d bytes of packet", p_sys->i_csa_pkt_size );
+            var_Get( p_mux, SOUT_CFG_PREFIX "csa-pkt", &pkt_val );
+            if( pkt_val.i_int < 12 || pkt_val.i_int > 188 )
+            {
+                msg_Err( p_mux, "wrong packet size %d specified.", pkt_val.i_int );
+                msg_Warn( p_mux, "using default packet size of 188 bytes" );
+                p_sys->i_csa_pkt_size = 188;
             }
+            else p_sys->i_csa_pkt_size = pkt_val.i_int;
+            msg_Dbg( p_mux, "encrypting %d bytes of packet", p_sys->i_csa_pkt_size );
         }
+        free( csa2.psz_string );
     }
     free( val.psz_string );
 
@@ -835,20 +865,74 @@ static void Close( vlc_object_t * p_this )
     sout_mux_sys_t      *p_sys = p_mux->p_sys;
     int i;
 
+    vlc_mutex_lock( &p_sys->csa_lock );
     if( p_sys->csa )
     {
+        var_DelCallback( p_mux, SOUT_CFG_PREFIX "csa-ck", ChangeKeyCallback, NULL );
+        var_DelCallback( p_mux, SOUT_CFG_PREFIX "csa2-ck", ChangeKeyCallback, NULL );
+        var_DelCallback( p_mux, SOUT_CFG_PREFIX "csa-use", ActiveKeyCallback, NULL );
         csa_Delete( p_sys->csa );
+        p_sys->csa = NULL;
     }
+    vlc_mutex_unlock( &p_sys->csa_lock );
+
     for( i = 0; i < MAX_PMT; i++ )
     {
         free( p_sys->sdt_descriptors[i].psz_service_name );
         free( p_sys->sdt_descriptors[i].psz_provider );
     }
 
+    vlc_mutex_destroy( &p_sys->csa_lock );
     free( p_sys->dvbpmt );
     free( p_sys );
 }
 
+/*****************************************************************************
+ * 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);
+    sout_mux_t      *p_mux = (sout_mux_t*)p_this;
+    sout_mux_sys_t  *p_sys = p_mux->p_sys;
+    int ret;
+
+    vlc_mutex_lock( &p_sys->csa_lock );
+    ret = csa_SetCW( p_this, p_sys->csa, newval.psz_string,
+                     !!(intptr_t)p_data );
+    vlc_mutex_unlock( &p_sys->csa_lock );
+
+    return ret;
+}
+
+/*****************************************************************************
+ * ActiveKeyCallback: called when changing the active (in use) encryption key on the fly.
+ *****************************************************************************/
+static int ActiveKeyCallback( 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); VLC_UNUSED(p_data);
+    sout_mux_t      *p_mux = (sout_mux_t*)p_this;
+    sout_mux_sys_t  *p_sys = p_mux->p_sys;
+    int             i_res = VLC_EBADVAR;
+
+    vlc_mutex_lock( &p_sys->csa_lock );
+    if( !strcmp(newval.psz_string, "odd" ) || !strcmp(newval.psz_string, "first" ) || !strcmp(newval.psz_string, "1" ) )
+    {
+        i_res = csa_UseKey( (vlc_object_t*)p_mux, p_sys->csa, 1 );
+    }
+    else if( !strcmp(newval.psz_string, "even" ) || !strcmp(newval.psz_string, "second" ) || !strcmp(newval.psz_string, "2" ) )
+    {
+        i_res = csa_UseKey( (vlc_object_t*)p_mux, p_sys->csa, 0 );
+    }
+    vlc_mutex_unlock( &p_sys->csa_lock );
+
+    return i_res;
+}
+
 /*****************************************************************************
  * Control:
  *****************************************************************************/
@@ -913,38 +997,43 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
         case VIDEO_ES:
             switch( p_input->p_fmt->i_codec )
             {
-                case VLC_FOURCC( 'm', 'p','g', 'v' ):
+                case VLC_CODEC_MPGV:
                     /* TODO: do we need to check MPEG-I/II ? */
                     p_stream->i_stream_type = 0x02;
                     p_stream->i_stream_id = 0xe0;
                     break;
-                case VLC_FOURCC( 'm', 'p','4', 'v' ):
+                case VLC_CODEC_MP4V:
                     p_stream->i_stream_type = 0x10;
                     p_stream->i_stream_id = 0xe0;
                     p_stream->i_es_id = p_stream->i_pid;
                     break;
-                case VLC_FOURCC( 'h', '2','6', '4' ):
+                case VLC_CODEC_H264:
                     p_stream->i_stream_type = 0x1b;
                     p_stream->i_stream_id = 0xe0;
                     break;
                 /* 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' ):
-                case VLC_FOURCC( 'W', 'M', 'V', '3' ):
-                case VLC_FOURCC( 'W', 'M', 'V', '2' ):
-                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' ):
-                case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
+                case VLC_CODEC_H263I:
+                case VLC_CODEC_H263:
+                case VLC_CODEC_WMV3:
+                case VLC_CODEC_WMV2:
+                case VLC_CODEC_WMV1:
+                case VLC_CODEC_DIV3:
+                case VLC_CODEC_DIV2:
+                case VLC_CODEC_DIV1:
+                case VLC_CODEC_MJPG:
                     p_stream->i_stream_type = 0xa0; /* private */
                     p_stream->i_stream_id = 0xa0;   /* beurk */
                     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;
                     break;
+                case VLC_CODEC_DIRAC:
+                    /* stream_id makes use of stream_id_extension */
+                    p_stream->i_stream_id = (PES_EXTENDED_STREAM_ID << 8) | 0x60;
+                    p_stream->i_stream_type = 0xd1;
+                    break;
                 default:
                     free( p_stream );
                     return VLC_EGENERIC;
@@ -955,30 +1044,33 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
         case AUDIO_ES:
             switch( p_input->p_fmt->i_codec )
             {
-                case VLC_FOURCC( 'm', 'p','g', 'a' ):
-                case VLC_FOURCC( 'm', 'p', '3', ' ' ):
+                case VLC_CODEC_MPGA:
                     p_stream->i_stream_type =
                         p_input->p_fmt->audio.i_rate >= 32000 ? 0x03 : 0x04;
                     p_stream->i_stream_id = 0xc0;
                     break;
-                case VLC_FOURCC( 'a', '5','2', ' ' ):
+                case VLC_CODEC_A52:
                     p_stream->i_stream_type = 0x81;
                     p_stream->i_stream_id = 0xbd;
                     break;
-                case VLC_FOURCC( 'l', 'p','c', 'm' ):
+                case VLC_CODEC_EAC3:
+                    p_stream->i_stream_type = 0x06;
+                    p_stream->i_stream_id = 0xbd;
+                    break;
+                case VLC_CODEC_DVD_LPCM:
                     p_stream->i_stream_type = 0x83;
                     p_stream->i_stream_id = 0xbd;
                     break;
-                case VLC_FOURCC( 'd', 't','s', ' ' ):
+                case VLC_CODEC_DTS:
                     p_stream->i_stream_type = 0x06;
                     p_stream->i_stream_id = 0xbd;
                     break;
-                case VLC_FOURCC( 'm', 'p','4', 'a' ):
+                case VLC_CODEC_MP4A:
                     /* XXX: make that configurable in some way when LOAS
                      * is implemented for AAC in TS */
                     //p_stream->i_stream_type = 0x11; /* LOAS/LATM */
                     p_stream->i_stream_type = 0x0f; /* ADTS */
-                    p_stream->i_stream_id = 0xfa;
+                    p_stream->i_stream_id = 0xc0;
                     p_sys->i_mpeg4_streams++;
                     p_stream->i_es_id = p_stream->i_pid;
                     break;
@@ -992,22 +1084,22 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
         case SPU_ES:
             switch( p_input->p_fmt->i_codec )
             {
-                case VLC_FOURCC( 's', 'p','u', ' ' ):
+                case VLC_CODEC_SPU:
                     p_stream->i_stream_type = 0x82;
                     p_stream->i_stream_id = 0xbd;
                     break;
-                case VLC_FOURCC( 's', 'u','b', 't' ):
+                case VLC_CODEC_SUBT:
                     p_stream->i_stream_type = 0x12;
                     p_stream->i_stream_id = 0xfa;
                     p_sys->i_mpeg4_streams++;
                     p_stream->i_es_id = p_stream->i_pid;
                     break;
-                case VLC_FOURCC('d','v','b','s'):
+                case VLC_CODEC_DVBS:
                     p_stream->i_stream_type = 0x06;
                     p_stream->i_es_id = p_input->p_fmt->subs.dvb.i_id;
                     p_stream->i_stream_id = 0xbd;
                     break;
-                case VLC_FOURCC('t','e','l','x'):
+                case VLC_CODEC_TELETEXT:
                     p_stream->i_stream_type = 0x06;
                     p_stream->i_stream_id = 0xbd; /* FIXME */
                     break;
@@ -1095,7 +1187,7 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
     }
 
     /* Create decoder specific info for subt */
-    if( p_stream->i_codec == VLC_FOURCC( 's', 'u','b', 't' ) )
+    if( p_stream->i_codec == VLC_CODEC_SUBT )
     {
         uint8_t *p;
 
@@ -1307,7 +1399,6 @@ static int Mux( sout_mux_t *p_mux )
             block_FifoEmpty( p_mux->pp_inputs[i]->p_fifo );
         }
         msg_Dbg( p_mux, "waiting for PCR streams" );
-        msleep( 1000 );
         return VLC_SUCCESS;
     }
     p_pcr_stream = (ts_stream_t*)p_sys->p_pcr_input->p_sys;
@@ -1399,12 +1490,12 @@ static int Mux( sout_mux_t *p_mux )
 
                     if( p_stream == p_pcr_stream || p_sys->b_data_alignment
                          || p_input->p_fmt->i_codec !=
-                             VLC_FOURCC('m', 'p', 'g', 'a') )
+                             VLC_CODEC_MPGA )
                     {
                         p_data = block_FifoGet( p_input->p_fifo );
 
                         if( p_input->p_fmt->i_codec ==
-                                VLC_FOURCC('m', 'p', '4', 'a' ) )
+                                VLC_CODEC_MP4A )
                             p_data = Add_ADTS( p_data, p_input->p_fmt );
                     }
                     else
@@ -1417,7 +1508,7 @@ static int Mux( sout_mux_t *p_mux )
                         p_data->i_length = p_next->i_dts - p_data->i_dts;
                     }
                     else if( p_input->p_fmt->i_codec !=
-                               VLC_FOURCC('s', 'u', 'b', 't' ) )
+                               VLC_CODEC_SUBT )
                         p_data->i_length = 1000;
 
                     if( ( p_pcr_stream->i_pes_dts > 0 &&
@@ -1451,11 +1542,12 @@ static int Mux( sout_mux_t *p_mux )
                     else
                     {
                         int i_header_size = 0;
+                        int i_max_pes_size = 0;
                         int b_data_alignment = 0;
                         if( p_input->p_fmt->i_cat == SPU_ES )
                         {
                             if( p_input->p_fmt->i_codec ==
-                                VLC_FOURCC('s','u','b','t') )
+                                VLC_CODEC_SUBT )
                             {
                                 /* Prepend header */
                                 p_data = block_Realloc( p_data, 2,
@@ -1494,14 +1586,14 @@ static int Mux( sout_mux_t *p_mux )
                                 }
                             }
                             else if( p_input->p_fmt->i_codec ==
-                                       VLC_FOURCC('t','e','l','x') )
+                                       VLC_CODEC_TELETEXT )
                             {
                                 /* EN 300 472 */
                                 i_header_size = 0x24;
                                 b_data_alignment = 1;
                             }
                             else if( p_input->p_fmt->i_codec ==
-                                       VLC_FOURCC('d','v','b','s') )
+                                       VLC_CODEC_DVBS )
                             {
                                 /* EN 300 743 */
                                 b_data_alignment = 1;
@@ -1530,9 +1622,19 @@ static int Mux( sout_mux_t *p_mux )
                             p_data->i_pts = p_data->i_dts;
                         }
 
+                        if( p_input->p_fmt->i_codec ==
+                                   VLC_CODEC_DIRAC )
+                        {
+                            b_data_alignment = 1;
+                            /* dirac pes packets should be unbounded in
+                             * length, specify a suitibly large max size */
+                            i_max_pes_size = INT_MAX;
+                        }
+
                          EStoPES ( p_mux->p_sout, &p_data, p_data,
                                        p_input->p_fmt, p_stream->i_stream_id,
-                                       1, b_data_alignment, i_header_size, 0 );
+                                       1, b_data_alignment, i_header_size,
+                                       i_max_pes_size );
 
                         BufferChainAppend( &p_stream->chain_pes, p_data );
 
@@ -1665,6 +1767,7 @@ static int Mux( sout_mux_t *p_mux )
 #define STD_PES_PAYLOAD 170
 static block_t *FixPES( sout_mux_t *p_mux, block_fifo_t *p_fifo )
 {
+    VLC_UNUSED(p_mux);
     block_t *p_data;
     size_t i_size;
 
@@ -1888,7 +1991,9 @@ static void TSDate( sout_mux_t *p_mux, sout_buffer_chain_t *p_chain_ts,
         }
         if( p_ts->i_flags & BLOCK_FLAG_SCRAMBLED )
         {
-            csa_Encrypt( p_sys->csa, p_ts->p_buffer, p_sys->i_csa_pkt_size, 0 );
+            vlc_mutex_lock( &p_sys->csa_lock );
+            csa_Encrypt( p_sys->csa, p_ts->p_buffer, p_sys->i_csa_pkt_size );
+            vlc_mutex_unlock( &p_sys->csa_lock );
         }
 
         /* latency */
@@ -1901,6 +2006,7 @@ static void TSDate( sout_mux_t *p_mux, sout_buffer_chain_t *p_chain_ts,
 static block_t *TSNew( sout_mux_t *p_mux, ts_stream_t *p_stream,
                        bool b_pcr )
 {
+    VLC_UNUSED(p_mux);
     block_t *p_pes = p_stream->chain_pes.p_first;
     block_t *p_ts;
 
@@ -2120,6 +2226,7 @@ static void PEStoTS( sout_instance_t *p_sout,
                      sout_buffer_chain_t *c, block_t *p_pes,
                      ts_stream_t *p_stream )
 {
+    VLC_UNUSED(p_sout);
     uint8_t *p_data;
     int     i_size;
     int     b_new_pes;
@@ -2211,6 +2318,7 @@ static void PEStoTS( sout_instance_t *p_sout,
 static block_t *WritePSISection( sout_instance_t *p_sout,
                                        dvbpsi_psi_section_t* p_section )
 {
+    VLC_UNUSED(p_sout);
     block_t   *p_psi, *p_first = NULL;
 
     while( p_section )
@@ -2435,13 +2543,14 @@ static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c )
                     bits_write( &bits, 8, 0x21 );   /* Visual 14496-2 */
                     bits_write( &bits, 6, 0x04 );   /* VisualStream */
                 }
-                else if( p_stream->i_stream_type == 0x11  || p_stream->i_stream_type == 0x0f )
+                else if( p_stream->i_stream_type == 0x11 ||
+                         p_stream->i_stream_type == 0x0f )
                 {
                     bits_write( &bits, 8, 0x40 );   /* Audio 14496-3 */
                     bits_write( &bits, 6, 0x05 );   /* AudioStream */
                 }
                 else if( p_stream->i_stream_type == 0x12 &&
-                         p_stream->i_codec == VLC_FOURCC('s','u','b','t') )
+                         p_stream->i_codec == VLC_CODEC_SUBT )
                 {
                     bits_write( &bits, 8, 0x0B );   /* Text Stream */
                     bits_write( &bits, 6, 0x04 );   /* VisualStream */
@@ -2502,7 +2611,7 @@ static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c )
                     GetDescriptorLength24b( bits.i_data -
                                             bits_fix_IOD.i_data - 3 ) );
 
-#if 0//def HAVE_BSEARCH /* FIXME!!! This can't possibly work */
+#if 0 /* FIXME!!! This can't possibly work */
         i_pidinput = p_mux->pp_inputs[i]->p_fmt->i_id;
         p_usepid = bsearch( &i_pidinput, p_sys->pmtmap, p_sys->i_pmtslots,
                             sizeof(pmt_map_t), intcompare );
@@ -2526,7 +2635,6 @@ static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c )
 
         p_stream = (ts_stream_t *)p_mux->pp_inputs[i_stream]->p_sys;
 
-#ifdef HAVE_BSEARCH
         i_pidinput = p_mux->pp_inputs[i_stream]->p_fmt->i_id;
         p_usepid = bsearch( &i_pidinput, p_sys->pmtmap, p_sys->i_pmtslots,
                             sizeof(pmt_map_t), intcompare );
@@ -2537,7 +2645,6 @@ static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c )
                     p_stream->i_stream_type, p_stream->i_pid );
         else
             /* If there's an error somewhere, dump it to the first pmt */
-#endif
             p_es = dvbpsi_PMTAddES( &p_sys->dvbpmt[0], p_stream->i_stream_type,
                                     p_stream->i_pid );
 
@@ -2578,7 +2685,14 @@ static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c )
             /* "registration" descriptor : "AC-3" */
             dvbpsi_PMTESAddDescriptor( p_es, 0x05, 4, format );
         }
-        else if( p_stream->i_codec == VLC_FOURCC('d','t','s',' ') )
+        else if( p_stream->i_codec == VLC_CODEC_DIRAC )
+        {
+            /* Dirac registration descriptor */
+
+            uint8_t data[4] = { 'd', 'r', 'a', 'c' };
+            dvbpsi_PMTESAddDescriptor( p_es, 0x05, 4, data );
+        }
+        else if( p_stream->i_codec == VLC_CODEC_DTS )
         {
             /* DTS registration descriptor (ETSI TS 101 154 Annex F) */
 
@@ -2586,7 +2700,12 @@ static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c )
             uint8_t data[4] = { 0x44, 0x54, 0x53, 0x32 };
             dvbpsi_PMTESAddDescriptor( p_es, 0x05, 4, data );
         }
-        else if( p_stream->i_codec == VLC_FOURCC('t','e','l','x') )
+        else if( p_stream->i_codec == VLC_CODEC_EAC3 )
+        {
+            uint8_t data[1] = { 0x00 };
+            dvbpsi_PMTESAddDescriptor( p_es, 0x7a, 1, data );
+        }
+        else if( p_stream->i_codec == VLC_CODEC_TELETEXT )
         {
             if( p_stream->i_decoder_specific_info )
             {
@@ -2596,7 +2715,7 @@ static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c )
             }
             continue;
         }
-        else if( p_stream->i_codec == VLC_FOURCC('d','v','b','s') )
+        else if( p_stream->i_codec == VLC_CODEC_DVBS )
         {
             /* DVB subtitles */
             if( p_stream->i_decoder_specific_info )