]> git.sesse.net Git - vlc/commitdiff
(Forward port from branch 0.8.1-jpsaman-thedj) TS demux can now dump a TS stream...
authorJean-Paul Saman <jpsaman@videolan.org>
Mon, 8 Aug 2005 09:16:09 +0000 (09:16 +0000)
committerJean-Paul Saman <jpsaman@videolan.org>
Mon, 8 Aug 2005 09:16:09 +0000 (09:16 +0000)
modules/demux/ts.c
modules/mux/mpeg/csa.c
modules/mux/mpeg/csa.h
modules/mux/mpeg/ts.c

index c04b1a3b5a2717cc037f80b3fbbe35045eca9141..8a1ca984b5b241b00790141ec6848a76c9a569f2 100644 (file)
@@ -1,10 +1,11 @@
 /*****************************************************************************
  * ts.c: Transport Stream input module for VLC.
  *****************************************************************************
- * Copyright (C) 2004 the VideoLAN team
+ * Copyright (C) 2004-2005 the VideoLAN team
  * $Id$
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *          Jean-Paul Saman <jpsaman #_at_# m2x.nl>
  *
  * 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
@@ -101,6 +102,24 @@ static void Close ( vlc_object_t * );
 #define CAPMT_SYSID_TEXT N_("CAPMT System ID")
 #define CAPMT_SYSID_LONGTEXT N_("only forward descriptors from this SysID to the CAM")
 
+#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. " )
+
+#define TSDUMP_TEXT N_("Filename of dump")
+#define TSDUMP_LONGTEXT N_("Specify a filename where to dump the TS in")
+
+#define APPEND_TEXT N_("Append")
+#define APPEND_LONGTEXT N_( \
+    "If the file exists and this option is selected, the existing file " \
+    "will not be overwritten." )
+
+#define DUMPSIZE_TEXT N_("Dump buffer size")
+#define DUMPSIZE_LONGTEXT N_( \
+    "Tweak the buffer size for reading and writing an integer number of packets." \
+    "Specify the size of the buffer here and not the number of packets." )
+
 vlc_module_begin();
     set_description( _("MPEG Transport Stream demuxer") );
     set_shortname ( "MPEG-TS" );
@@ -113,8 +132,14 @@ vlc_module_begin();
     add_integer( "ts-out-mtu", 1500, NULL, MTUOUT_TEXT,
                  MTUOUT_LONGTEXT, VLC_TRUE );
     add_string( "ts-csa-ck", NULL, NULL, CSA_TEXT, CSA_LONGTEXT, VLC_TRUE );
+    add_integer( "ts-csa-pkt", 188, NULL, CPKT_TEXT, CPKT_LONGTEXT, VLC_TRUE );    
     add_bool( "ts-silent", 0, NULL, SILENT_TEXT, SILENT_LONGTEXT, VLC_TRUE );
 
+    add_file( "ts-dump-file", NULL, NULL, TSDUMP_TEXT, TSDUMP_LONGTEXT, VLC_FALSE );
+    add_bool( "ts-dump-append", 0, NULL, APPEND_TEXT, APPEND_LONGTEXT, VLC_FALSE );
+    add_integer( "ts-dump-size", 16384, NULL, DUMPSIZE_TEXT,
+                 DUMPSIZE_LONGTEXT, VLC_TRUE );
+
     set_capability( "demux2", 10 );
     set_callbacks( Open, Close );
     add_shortcut( "ts" );
@@ -284,6 +309,7 @@ struct demux_sys_t
     /* */
     vlc_bool_t  b_es_id_pid;
     csa_t       *csa;
+    int         i_csa_pkt_size;
     vlc_bool_t  b_silent;
 
     vlc_bool_t  b_udp_out;
@@ -294,14 +320,20 @@ struct demux_sys_t
     int         i_dvb_program;
     vlc_list_t  *p_programs_list;
 
+    /* TS dump */
+    char        *psz_file;  /* file to dump data in */
+    FILE        *p_file;    /* filehandle */
+    uint64_t    i_write;    /* bytes written */
+    vlc_bool_t  b_file_out; /* dump mode enabled */
+    
     /* */
     vlc_bool_t  b_meta;
 };
 
-static int Demux  ( demux_t *p_demux );
+static int Demux    ( demux_t *p_demux );
+static int DemuxFile( demux_t *p_demux );
 static int Control( demux_t *p_demux, int i_query, va_list args );
 
-
 static void PIDInit ( ts_pid_t *pid, vlc_bool_t b_psi, ts_psi_t *p_owner );
 static void PIDClean( es_out_t *out, ts_pid_t *pid );
 static int  PIDFillFormat( ts_pid_t *pid, int i_stream_type );
@@ -313,7 +345,6 @@ static void PSINewTableCallBack( demux_t *, dvbpsi_handle,
                                  uint8_t  i_table_id, uint16_t i_extension );
 #endif
 
-
 static inline int PIDGet( block_t *p )
 {
     return ( (p->p_buffer[1]&0x1f)<<8 )|p->p_buffer[2];
@@ -343,7 +374,9 @@ static int Open( vlc_object_t *p_this )
     int          i_sync, i_peek, i;
     int          i_packet_size;
 
-    ts_pid_t     *pat;
+    ts_pid_t    *pat;
+    char        *psz_mode;
+    vlc_bool_t   b_append;
 
     vlc_value_t  val;
 
@@ -396,8 +429,61 @@ static int Open( vlc_object_t *p_this )
         return VLC_EGENERIC;
     }
 
+    p_sys->i_packet_size = i_packet_size;
+
+    /* Fill dump mode fields */
+    p_sys->i_write = 0;
+    p_sys->p_file = NULL;
+    p_sys->b_file_out = VLC_FALSE;
+    p_sys->psz_file = var_CreateGetString( p_demux, "ts-dump-file" );
+    if( *p_sys->psz_file != '\0' )
+    {
+        p_sys->b_file_out = VLC_TRUE;
+
+        var_Create( p_demux, "ts-dump-append", VLC_VAR_BOOL|VLC_VAR_DOINHERIT );
+        var_Get( p_demux, "ts-dump-append", &val );
+        b_append = val.b_bool;
+        if ( b_append )
+            psz_mode = "ab";
+        else
+            psz_mode = "wb";
+
+        if( !strcmp( p_sys->psz_file, "-" ) )
+        {
+            msg_Info( p_demux, "dumping raw stream to standard output" );
+            p_sys->p_file = stdout;
+        }
+        else if( ( p_sys->p_file = fopen( p_sys->psz_file, psz_mode ) ) == NULL )
+        {
+            msg_Err( p_demux, "cannot create `%s' for writing", p_sys->psz_file );
+            p_sys->b_file_out = VLC_FALSE;
+        }
+
+        if( p_sys->b_file_out )
+        {
+            vlc_value_t bufsize;
+
+            /* Determine how many packets to read. */
+            var_Create( p_demux, "ts-dump-size",
+                        VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
+            var_Get( p_demux, "ts-dump-size", &bufsize );
+            p_sys->i_ts_read = (int) (bufsize.i_int / p_sys->i_packet_size);
+            if( p_sys->i_ts_read <= 0 )
+            {
+                p_sys->i_ts_read = 1500 / p_sys->i_packet_size;
+            }
+            p_sys->buffer = malloc( p_sys->i_packet_size * p_sys->i_ts_read );
+            msg_Info( p_demux, "%s raw stream to file `%s' reading packets %d",
+                      b_append ? "appending" : "dumping", p_sys->psz_file,
+                      p_sys->i_ts_read );
+        }
+    }
+
     /* Fill p_demux field */
-    p_demux->pf_demux = Demux;
+    if( p_sys->b_file_out )
+        p_demux->pf_demux = DemuxFile;
+    else
+        p_demux->pf_demux = Demux;
     p_demux->pf_control = Control;
     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
     memset( p_sys, 0, sizeof( demux_sys_t ) );
@@ -459,7 +545,7 @@ static int Open( vlc_object_t *p_this )
 
     var_Create( p_demux, "ts-out", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
     var_Get( p_demux, "ts-out", &val );
-    if( val.psz_string && *val.psz_string )
+    if( val.psz_string && *val.psz_string && !p_sys->b_file_out )
     {
         vlc_value_t mtu;
         char *psz = strchr( val.psz_string, ':' );
@@ -499,7 +585,6 @@ static int Open( vlc_object_t *p_this )
         free( val.psz_string );
     }
 
-
     /* We handle description of an extra PMT */
     var_Create( p_demux, "ts-extra-pmt", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
     var_Get( p_demux, "ts-extra-pmt", &val );
@@ -597,13 +682,28 @@ static int Open( vlc_object_t *p_this )
             {
                 ck[i] = ( i_ck >> ( 56 - 8*i) )&0xff;
             }
-
+#ifndef TS_NO_CSA_CK_MSG
             msg_Dbg( p_demux, "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();
-            csa_SetCW( p_sys->csa, ck, ck );
+            
+            if( p_sys->csa )
+            {
+                csa_SetCW( p_sys->csa, ck, ck );
+            
+                var_Create( p_demux, "ts-csa-pkt", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
+                var_Get( p_demux, "ts-csa-pkt", &val );
+                if( val.i_int < 4 || val.i_int > 188 )
+                {
+                    msg_Err( p_demux, "wrong packet size %d specified.", val.i_int );
+                    msg_Warn( p_demux, "using default packet size of 188 bytes" );
+                    p_sys->i_csa_pkt_size = 188;
+                }
+                else p_sys->i_csa_pkt_size = val.i_int;
+                msg_Dbg( p_demux, "decrypting %d bytes of packet", p_sys->i_csa_pkt_size );
+            }
         }
     }
     if( val.psz_string )
@@ -691,9 +791,135 @@ static void Close( vlc_object_t *p_this )
         var_Change( p_demux, "programs", VLC_VAR_FREELIST, &val, NULL );
     }
 
+    /* If in dump mode, then close the file */
+    if( p_sys->b_file_out )
+    {
+        msg_Info( p_demux ,"closing %s ("I64Fd" Kbytes dumped)", p_sys->psz_file,
+                  p_sys->i_write / 1024 );
+
+        if( p_sys->p_file != stdout )
+        {
+            fclose( p_sys->p_file );
+            p_sys->p_file = NULL;
+        }
+        free( p_sys->psz_file );
+        p_sys->psz_file = NULL;
+
+        free( p_sys->buffer );
+    }
+
     free( p_sys );
 }
 
+/*****************************************************************************
+ * DemuxFile:
+ *****************************************************************************/
+static int DemuxFile( demux_t *p_demux )
+{    
+    demux_sys_t *p_sys = p_demux->p_sys;
+    uint8_t     *p_buffer = p_sys->buffer; /* Put first on sync byte */
+    int i_diff= 0;
+    int i_data= 0;
+    int i_pos = 0;
+    int i_bufsize = p_sys->i_packet_size * p_sys->i_ts_read;
+    
+    i_data = stream_Read( p_demux->s, p_sys->buffer, i_bufsize );
+    if( (i_data <= 0) && (i_data < p_sys->i_packet_size) )
+    {
+        msg_Dbg( p_demux, "Error reading malformed packets" );
+        return i_data;
+    }
+
+    /* Test continuity counter */
+    while( i_pos < i_data )
+    {
+        ts_pid_t    *p_pid;   /* point to a PID structure */
+        vlc_bool_t b_payload; /* indicates a packet with payload */
+        vlc_bool_t b_adaptation; /* adaptation field */
+        int i_cc  = 0;        /* continuity counter */
+    
+        if( p_sys->buffer[i_pos] != 0x47 )
+        {
+            msg_Warn( p_demux, "lost sync" );
+            while( !p_demux->b_die && (i_pos < i_data) )
+            {
+                i_pos++;
+                if( p_sys->buffer[i_pos] == 0x47 )
+                    break;
+            }
+            if( !p_demux->b_die )
+                msg_Warn( p_demux, "sync found" );
+        }
+        
+        /* continuous when (one of this):
+         * diff == 1
+         * diff == 0 and payload == 0
+         * diff == 0 and duplicate packet (playload != 0) <- should we
+         *   test the content ?
+         */
+        i_cc  = p_buffer[i_pos+3]&0x0f;
+        b_payload = p_buffer[i_pos+3]&0x10;
+        b_adaptation = p_buffer[i_pos+3]&0x20;
+        
+        /* Get the PID */
+        p_pid = &p_sys->pid[ ((p_buffer[i_pos+1]&0x1f)<<8)|p_buffer[i_pos+2] ];
+        
+        /* Detect discontinuity indicator in adaptation field */
+        if( b_adaptation )
+        {
+            if( p_buffer[i_pos+5]&0x80 )
+                msg_Warn( p_demux, "discontinuity indicator (pid=%d) ", p_pid->i_pid );
+            if( p_buffer[i_pos+5]&0x40 )
+                msg_Warn( p_demux, "random access indicator (pid=%d) ", p_pid->i_pid );
+        }
+        i_diff = ( i_cc - p_pid->i_cc )&0x0f;
+        if( b_payload && i_diff == 1 )
+        {
+            p_pid->i_cc++;
+        }
+        else
+        {
+            if( p_pid->i_cc == 0xff )
+            {
+                msg_Warn( p_demux, "first packet for pid=%d cc=0x%x",
+                        p_pid->i_pid, i_cc );
+                p_pid->i_cc = i_cc;
+            }
+            else if( i_diff != 0 )
+            {
+                /* FIXME what to do when discontinuity_indicator is set ? */
+                msg_Warn( p_demux, "transport error detected 0x%x instead of 0x%x",
+                          i_cc, ( p_pid->i_cc + 1 )&0x0f );
+    
+                p_pid->i_cc = i_cc;
+                /* Mark transport error in the TS packet. */
+                p_buffer[i_pos+1] |= 0x80;
+            }
+        }
+        
+        /* Test if user wants to decrypt it first */
+        if( p_sys->csa )
+            csa_Decrypt( p_demux->p_sys->csa, &p_buffer[i_pos], p_demux->p_sys->i_csa_pkt_size );
+        
+        i_pos += p_sys->i_packet_size;
+    }
+
+    /* Then write */
+    i_data = fwrite( p_sys->buffer, 1, i_data, p_sys->p_file );
+    if( i_data < 0 )
+    {
+        msg_Err( p_demux, "failed to write data" );
+        return -1;
+    }
+#if 0
+    msg_Dbg( p_demux, "dumped %d bytes", i_data );
+#endif
+
+    p_sys->i_write += i_data;
+    return 1;
+}
+
 /*****************************************************************************
  * Demux:
  *****************************************************************************/
@@ -837,6 +1063,9 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
     int64_t i64;
     int i_int;
 
+    if( p_sys->b_file_out )
+        return demux2_vaControlHelper( p_demux->s, 0, -1, 0, 1, i_query, args );
+
     switch( i_query )
     {
         case DEMUX_GET_POSITION:
@@ -1409,7 +1638,7 @@ static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk )
 
     if( p_demux->p_sys->csa )
     {
-        csa_Decrypt( p_demux->p_sys->csa, p_bk->p_buffer );
+        csa_Decrypt( p_demux->p_sys->csa, p_bk->p_buffer, p_demux->p_sys->i_csa_pkt_size );
     }
 
     if( !b_adaptation )
@@ -1682,7 +1911,9 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data )
     p_iod = malloc( sizeof( iod_descriptor_t ) );
     memset( p_iod, 0, sizeof( iod_descriptor_t ) );
 
+#ifdef DEBUG
     fprintf( stderr, "\n************ IOD ************" );
+#endif
     for( i = 0; i < 255; i++ )
     {
         p_iod->es_descr[i].b_ok = 0;
@@ -1709,10 +1940,11 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data )
         p_iod->i_iod_label = byte2;
         i_iod_tag = byte3;
     }
+#ifdef DEBUG
     fprintf( stderr, "\n* iod_label:%d", p_iod->i_iod_label );
     fprintf( stderr, "\n* ===========" );
     fprintf( stderr, "\n* tag:0x%x", i_iod_tag );
-
+#endif
     if( i_iod_tag != 0x02 )
     {
         fprintf( stderr, "\n ERR: tag %02x != 0x02", i_iod_tag );
@@ -1720,7 +1952,9 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data )
     }
 
     i_iod_length = IODDescriptorLength( &i_data, &p_data );
+#ifdef DEBUG    
     fprintf( stderr, "\n* length:%d", i_iod_length );
+#endif
     if( i_iod_length > i_data )
     {
         i_iod_length = i_data;
@@ -1730,16 +1964,18 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data )
     i_flags = IODGetByte( &i_data, &p_data );
     p_iod->i_od_id |= i_flags >> 6;
     b_url = ( i_flags >> 5  )&0x01;
-
+#ifdef DEBUG
     fprintf( stderr, "\n* od_id:%d", p_iod->i_od_id );
     fprintf( stderr, "\n* url flag:%d", b_url );
     fprintf( stderr, "\n* includeInlineProfileLevel flag:%d", ( i_flags >> 4 )&0x01 );
-
+#endif
     if( b_url )
     {
         p_iod->psz_url = IODGetURL( &i_data, &p_data );
+#ifdef DEBUG        
         fprintf( stderr, "\n* url string:%s", p_iod->psz_url );
         fprintf( stderr, "\n*****************************\n" );
+#endif        
         return p_iod;
     }
     else
@@ -1752,13 +1988,13 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data )
     p_iod->i_audioProfileLevelIndication = IODGetByte( &i_data, &p_data );
     p_iod->i_visualProfileLevelIndication = IODGetByte( &i_data, &p_data );
     p_iod->i_graphicsProfileLevelIndication = IODGetByte( &i_data, &p_data );
-
+#ifdef DEBUG
     fprintf( stderr, "\n* ODProfileLevelIndication:%d", p_iod->i_ODProfileLevelIndication );
     fprintf( stderr, "\n* sceneProfileLevelIndication:%d", p_iod->i_sceneProfileLevelIndication );
     fprintf( stderr, "\n* audioProfileLevelIndication:%d", p_iod->i_audioProfileLevelIndication );
     fprintf( stderr, "\n* visualProfileLevelIndication:%d", p_iod->i_visualProfileLevelIndication );
     fprintf( stderr, "\n* graphicsProfileLevelIndication:%d", p_iod->i_graphicsProfileLevelIndication );
-
+#endif
 
     while( i_data > 0 && i_es_index < 255)
     {
@@ -1780,7 +2016,9 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data )
                 {
 #define es_descr    p_iod->es_descr[i_es_index]
                     int i_decoderConfigDescr_length;
+#ifdef DEBUG
                     fprintf( stderr, "\n* - ES_Descriptor length:%d", i_length );
+#endif
                     es_descr.b_ok = 1;
 
                     es_descr.i_es_id = IODGetWord( &i_data, &p_data );
@@ -1789,20 +2027,25 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data )
                     b_url = ( i_flags >> 6 )&0x01;
                     es_descr.b_OCRStreamFlag = ( i_flags >> 5 )&0x01;
                     es_descr.i_streamPriority = i_flags & 0x1f;
+#ifdef DEBUG
                     fprintf( stderr, "\n*   * streamDependenceFlag:%d", es_descr.b_streamDependenceFlag );
                     fprintf( stderr, "\n*   * OCRStreamFlag:%d", es_descr.b_OCRStreamFlag );
                     fprintf( stderr, "\n*   * streamPriority:%d", es_descr.i_streamPriority );
-
+#endif
                     if( es_descr.b_streamDependenceFlag )
                     {
                         es_descr.i_dependOn_es_id = IODGetWord( &i_data, &p_data );
+#ifdef DEBUG
                         fprintf( stderr, "\n*   * dependOn_es_id:%d", es_descr.i_dependOn_es_id );
+#endif
                     }
 
                     if( b_url )
                     {
                         es_descr.psz_url = IODGetURL( &i_data, &p_data );
+#ifdef DEBUG
                         fprintf( stderr, "\n* url string:%s", es_descr.psz_url );
+#endif
                     }
                     else
                     {
@@ -1812,18 +2055,23 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data )
                     if( es_descr.b_OCRStreamFlag )
                     {
                         es_descr.i_OCR_es_id = IODGetWord( &i_data, &p_data );
+#ifdef DEBUG
                         fprintf( stderr, "\n*   * OCR_es_id:%d", es_descr.i_OCR_es_id );
+#endif
                     }
 
                     if( IODGetByte( &i_data, &p_data ) != 0x04 )
                     {
+#ifdef DEBUG
                         fprintf( stderr, "\n* ERR missing DecoderConfigDescr" );
+#endif
                         es_descr.b_ok = 0;
                         break;
                     }
                     i_decoderConfigDescr_length = IODDescriptorLength( &i_data, &p_data );
-
+#ifdef DEBUG
                     fprintf( stderr, "\n*   - DecoderConfigDesc length:%d", i_decoderConfigDescr_length );
+#endif                    
 #define dec_descr   es_descr.dec_descr
                     dec_descr.i_objectTypeIndication = IODGetByte( &i_data, &p_data );
                     i_flags = IODGetByte( &i_data, &p_data );
@@ -1832,12 +2080,14 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data )
                     dec_descr.i_bufferSizeDB = IODGet3Bytes( &i_data, &p_data );
                     dec_descr.i_maxBitrate = IODGetDWord( &i_data, &p_data );
                     dec_descr.i_avgBitrate = IODGetDWord( &i_data, &p_data );
+#ifdef DEBUG                    
                     fprintf( stderr, "\n*     * objectTypeIndication:0x%x", dec_descr.i_objectTypeIndication  );
                     fprintf( stderr, "\n*     * streamType:0x%x", dec_descr.i_streamType );
                     fprintf( stderr, "\n*     * upStream:%d", dec_descr.b_upStream );
                     fprintf( stderr, "\n*     * bufferSizeDB:%d", dec_descr.i_bufferSizeDB );
                     fprintf( stderr, "\n*     * maxBitrate:%d", dec_descr.i_maxBitrate );
                     fprintf( stderr, "\n*     * avgBitrate:%d", dec_descr.i_avgBitrate );
+#endif                    
                     if( i_decoderConfigDescr_length > 13 && IODGetByte( &i_data, &p_data ) == 0x05 )
                     {
                         int i;
@@ -1867,15 +2117,20 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data )
 
                     if( IODGetByte( &i_data, &p_data ) != 0x06 )
                     {
+#ifdef DEBUG                    
                         fprintf( stderr, "\n* ERR missing SLConfigDescr" );
+#endif
                         es_descr.b_ok = 0;
                         break;
                     }
                     i_SLConfigDescr_length = IODDescriptorLength( &i_data, &p_data );
-
+#ifdef DEBUG
                     fprintf( stderr, "\n*   - SLConfigDescr length:%d", i_SLConfigDescr_length );
+#endif
                     i_predefined = IODGetByte( &i_data, &p_data );
+#ifdef DEBUG
                     fprintf( stderr, "\n*     * i_predefined:0x%x", i_predefined  );
+#endif
                     switch( i_predefined )
                     {
                         case 0x01:
@@ -1911,7 +2166,9 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data )
                             }
                             break;
                         default:
+#ifdef DEBUG                        
                             fprintf( stderr, "\n* ERR unsupported SLConfigDescr predefined" );
+#endif                            
                             es_descr.b_ok = 0;
                             break;
                     }
@@ -1920,7 +2177,9 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data )
 #undef  sl_descr
 #undef  es_descr
             default:
+#ifdef DEBUG            
                 fprintf( stderr, "\n* - OD tag:0x%x length:%d (Unsupported)", i_tag, i_length );
+#endif                
                 break;
         }
 
@@ -1928,9 +2187,9 @@ static iod_descriptor_t *IODNew( int i_data, uint8_t *p_data )
         i_data = i_data_sav - i_length;
         i_es_index++;
     }
-
-
+#ifdef DEBUG
     fprintf( stderr, "\n*****************************\n" );
+#endif    
     return p_iod;
 }
 
index c0e405d96e062c444fadddedb7419b82a1c33b9b..988d67d76ce84f2febe72902fcb31badf4283dfe 100644 (file)
@@ -1,10 +1,11 @@
 /*****************************************************************************
  * libcsa.c: CSA scrambler/descrambler
  *****************************************************************************
- * Copyright (C) 2004 Laurent Aimar
+ * Copyright (C) 2004-2005 Laurent Aimar
  * $Id$
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *          Jean-Paul Saman <jpsaman #_at_# m2x.nl>
  *
  * 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
@@ -89,7 +90,7 @@ void csa_SetCW( csa_t *c, uint8_t o_ck[8], uint8_t e_ck[8] )
 /*****************************************************************************
  * csa_Decrypt:
  *****************************************************************************/
-void csa_Decrypt( csa_t *c, uint8_t *pkt )
+void csa_Decrypt( csa_t *c, uint8_t *pkt, int i_pkt_size )
 {
     uint8_t *ck;
     uint8_t *kk;
@@ -133,8 +134,11 @@ void csa_Decrypt( csa_t *c, uint8_t *pkt )
     csa_StreamCypher( c, 1, ck, &pkt[i_hdr], ib );
 
     /* */
-    n = (188 - i_hdr) / 8;
-    i_residue = (188 - i_hdr) % 8;
+    n = (i_pkt_size - i_hdr) / 8;
+    if( n < 0 )
+        return;
+        
+    i_residue = (i_pkt_size - i_hdr) % 8;    
     for( i = 1; i < n + 1; i++ )
     {
         csa_BlockDecypher( kk, ib, block );
@@ -167,7 +171,7 @@ void csa_Decrypt( csa_t *c, uint8_t *pkt )
         csa_StreamCypher( c, 0, ck, NULL, stream );
         for( j = 0; j < i_residue; j++ )
         {
-            pkt[188 - i_residue + j] ^= stream[j];
+            pkt[i_pkt_size - i_residue + j] ^= stream[j];
         }
     }
 }
@@ -175,13 +179,13 @@ void csa_Decrypt( csa_t *c, uint8_t *pkt )
 /*****************************************************************************
  * csa_Encrypt:
  *****************************************************************************/
-void csa_Encrypt( csa_t *c, uint8_t *pkt, int b_odd )
+void csa_Encrypt( csa_t *c, uint8_t *pkt, int i_pkt_size, int b_odd )
 {
     uint8_t *ck;
     uint8_t *kk;
 
     int i, j;
-    int i_hdr;
+    int i_hdr = 4; /* hdr len */
     uint8_t  ib[184/8+2][8], stream[8], block[8];
     int n, i_residue;
 
@@ -210,10 +214,10 @@ void csa_Encrypt( csa_t *c, uint8_t *pkt, int b_odd )
         /* skip adaption field */
         i_hdr += pkt[4] + 1;
     }
-    n = (188 - i_hdr) / 8;
-    i_residue = (188 - i_hdr) % 8;
+    n = (i_pkt_size - i_hdr) / 8;
+    i_residue = (i_pkt_size - i_hdr) % 8;
 
-    if( n == 0 )
+    if( n <= 0 )
     {
         pkt[3] &= 0x3f;
         return;
@@ -253,7 +257,7 @@ void csa_Encrypt( csa_t *c, uint8_t *pkt, int b_odd )
         csa_StreamCypher( c, 0, ck, NULL, stream );
         for( j = 0; j < i_residue; j++ )
         {
-            pkt[188 - i_residue + j] ^= stream[j];
+            pkt[i_pkt_size - i_residue + j] ^= stream[j];
         }
     }
 }
index 3d71e61024c2b53327d8d0d517d1270ba7179f9a..05ba55dbaf5e926c96133f7c397800d661e7f4c2 100644 (file)
@@ -21,6 +21,9 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
 
+#ifndef _CSA_H
+#define _CSA_H 1
+
 typedef struct csa_t csa_t;
 #define csa_New     E_(__csa_New)
 #define csa_Delete  E_(__csa_Delete)
@@ -33,6 +36,7 @@ void   csa_Delete( csa_t * );
 
 void   csa_SetCW( csa_t *, uint8_t o_ck[8], uint8_t e_ck[8] );
 
-void   csa_Decrypt( csa_t *, uint8_t *pkt );
-void   csa_Encrypt( csa_t *, uint8_t *pkt, int b_odd );
+void   csa_Decrypt( csa_t *, uint8_t *pkt, int i_pkt_size );
+void   csa_Encrypt( csa_t *, uint8_t *pkt, int i_pkt_size, int b_odd );
 
+#endif /* _CSA_H */
index 6301128f11c5ecc153316f2285b506910155a13a..357c2dfed6015e86d6ad13d798ba44cca78a4656 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *          Eric Petit <titer@videolan.org>
+ *          Jean-Paul Saman <jpsaman #_at_# m2x.nl> 
  *
  * 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
@@ -130,6 +131,11 @@ static void    Close  ( vlc_object_t * );
 #define CK_LONGTEXT N_("Defines the CSA encryption key. This must be a " \
   "16 char string (8 hexadecimal bytes).")
 
+#define CPKT_TEXT N_("Packet size in bytes to encrypt")
+#define CPKT_LONGTEXT N_("Specify the 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-"
 
 vlc_module_begin();
@@ -176,6 +182,7 @@ vlc_module_begin();
 
     add_string( SOUT_CFG_PREFIX "csa-ck", NULL, NULL, CK_TEXT, CK_LONGTEXT,
                 VLC_TRUE );
+    add_integer( SOUT_CFG_PREFIX "csa-pkt", 188, NULL, CPKT_TEXT, CPKT_LONGTEXT, VLC_TRUE );
 
     set_callbacks( Open, Close );
 vlc_module_end();
@@ -186,7 +193,7 @@ vlc_module_end();
 static const char *ppsz_sout_options[] = {
     "pid-video", "pid-audio", "pid-spu", "pid-pmt", "tsid", "program-pmt",
     "es-id-pid", "shaping", "pcr", "bmin", "bmax", "use-key-frames",
-    "dts-delay", "csa-ck", "crypt-audio", "crypt-video",
+    "dts-delay", "csa-ck", "csa-pkt", "crypt-audio", "crypt-video",
     NULL
 };
 
@@ -203,6 +210,7 @@ static inline void BufferChainInit  ( sout_buffer_chain_t *c )
     c->p_first = NULL;
     c->pp_last = &c->p_first;
 }
+
 static inline void BufferChainAppend( sout_buffer_chain_t *c, block_t *b )
 {
     *c->pp_last = b;
@@ -215,6 +223,7 @@ static inline void BufferChainAppend( sout_buffer_chain_t *c, block_t *b )
     }
     c->pp_last = &b->p_next;
 }
+
 static inline block_t *BufferChainGet( sout_buffer_chain_t *c )
 {
     block_t *b = c->p_first;
@@ -233,12 +242,14 @@ static inline block_t *BufferChainGet( sout_buffer_chain_t *c )
     }
     return b;
 }
+
 static inline block_t *BufferChainPeek( sout_buffer_chain_t *c )
 {
     block_t *b = c->p_first;
 
     return b;
 }
+
 static inline void BufferChainClean( sout_instance_t *p_sout,
                                      sout_buffer_chain_t *c )
 {
@@ -293,14 +304,14 @@ struct sout_mux_sys_t
     int             i_pid_video;
     int             i_pid_audio;
     int             i_pid_spu;
-    int             i_pid_free; // first usable pid
+    int             i_pid_free; /* first usable pid */
 
     int             i_tsid;
     int             i_pat_version_number;
     ts_stream_t     pat;
 
     int             i_pmt_version_number;
-    ts_stream_t     pmt;        // Up to now only one program
+    ts_stream_t     pmt;        /* Up to now only one program */
     int             i_pmt_program_number;
 
     int             i_mpeg4_streams;
@@ -321,11 +332,11 @@ struct sout_mux_sys_t
     mtime_t             i_pcr;  /* last PCR emited */
 
     csa_t               *csa;
+    int                 i_csa_pkt_size;
     vlc_bool_t          b_crypt_audio;
     vlc_bool_t          b_crypt_video;
 };
 
-
 /* Reserve a pid and return it */
 static int  AllocatePID( sout_mux_sys_t *p_sys, int i_cat )
 {
@@ -542,12 +553,25 @@ static int Open( vlc_object_t *p_this )
             {
                 ck[i] = ( i_ck >> ( 56 - 8*i) )&0xff;
             }
-
+#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();
-            csa_SetCW( p_sys->csa, ck, ck );
+            if( p_sys->csa )
+            {
+                csa_SetCW( p_sys->csa, ck, ck );
+                
+                var_Get( p_mux, SOUT_CFG_PREFIX "csa-pkt", &val );
+                if( val.i_int < 12 || val.i_int > 188 )
+                {
+                    msg_Err( p_mux, "wrong packet size %d specified.", 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 = val.i_int;
+                msg_Dbg( p_mux, "encrypting %d bytes of packet", p_sys->i_csa_pkt_size );
+            }    
         }
     }
     if( val.psz_string ) free( val.psz_string );
@@ -663,8 +687,8 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
                 case VLC_FOURCC( 'D', 'I', 'V', '2' ):
                 case VLC_FOURCC( 'D', 'I', 'V', '1' ):
                 case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
-                    p_stream->i_stream_type = 0xa0; // private
-                    p_stream->i_stream_id = 0xa0;   // beurk
+                    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;
@@ -773,7 +797,6 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
         }
     }
 
-
     /* Copy extra data (VOL for MPEG-4 and extra BitMapInfoHeader for VFW */
     p_stream->i_decoder_specific_info = p_input->p_fmt->i_extra;
     if( p_stream->i_decoder_specific_info > 0 )
@@ -1496,7 +1519,7 @@ 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, 0 );
+            csa_Encrypt( p_sys->csa, p_ts->p_buffer, p_sys->i_csa_pkt_size, 0 );
         }
 
         /* latency */
@@ -1811,7 +1834,6 @@ static block_t *WritePSISection( sout_instance_t *p_sout,
 {
     block_t   *p_psi, *p_first = NULL;
 
-
     while( p_section )
     {
         int             i_size;
@@ -1825,7 +1847,7 @@ static block_t *WritePSISection( sout_instance_t *p_sout,
         p_psi->i_length = 0;
         p_psi->i_buffer = i_size + 1;
 
-        p_psi->p_buffer[0] = 0; // pointer
+        p_psi->p_buffer[0] = 0; /* pointer */
         memcpy( p_psi->p_buffer + 1,
                 p_section->p_data,
                 i_size );
@@ -1847,14 +1869,14 @@ static void GetPAT( sout_mux_t *p_mux,
     dvbpsi_psi_section_t *p_section;
 
     dvbpsi_InitPAT( &pat, p_sys->i_tsid, p_sys->i_pat_version_number,
-                    1 );      // b_current_next
+                    1 );      /* b_current_next */
     /* add all program (only one) */
     dvbpsi_PATAddProgram( &pat,
-                          p_sys->i_pmt_program_number,                    // i_number
-                          p_sys->pmt.i_pid );   // i_pid
+                          p_sys->i_pmt_program_number, /* i_number */
+                          p_sys->pmt.i_pid );   /* i_pid */
 
     p_section = dvbpsi_GenPATSections( &pat,
-                                       0 );     // max program per section
+                                       0 );     /* max program per section */
 
     p_pat = WritePSISection( p_mux->p_sout, p_section );
 
@@ -1888,9 +1910,9 @@ static void GetPMT( sout_mux_t *p_mux,
     int                 i_stream;
 
     dvbpsi_InitPMT( &pmt,
-                    p_sys->i_pmt_program_number,   // program number
+                    p_sys->i_pmt_program_number,   /* program number */
                     p_sys->i_pmt_version_number,
-                    1,      // b_current_next
+                    1,      /* b_current_next */
                     p_sys->i_pcr_pid );
 
     if( p_sys->i_mpeg4_streams > 0 )
@@ -1905,25 +1927,25 @@ static void GetPMT( sout_mux_t *p_mux,
         memset( iod, 0, 4096 );
 
         bits_initwrite( &bits, 4096, iod );
-       // IOD_label_scope
+        /* IOD_label_scope */
         bits_write( &bits, 8,   0x11 );
-        // IOD_label
+        /* IOD_label */
         bits_write( &bits, 8,   0x01 );
-        // InitialObjectDescriptor
+        /* InitialObjectDescriptor */
         bits_align( &bits );
-        bits_write( &bits, 8,   0x02 );     // tag
-        bits_fix_IOD = bits;    // save states to fix length later
+        bits_write( &bits, 8,   0x02 );     /* tag */
+        bits_fix_IOD = bits;    /* save states to fix length later */
         bits_write( &bits, 24,
-            GetDescriptorLength24b( 0 ) ); // variable length (fixed later)
-        bits_write( &bits, 10,  0x01 );     // ObjectDescriptorID
-        bits_write( &bits, 1,   0x00 );     // URL Flag
-        bits_write( &bits, 1,   0x00 );     // includeInlineProfileLevelFlag
-        bits_write( &bits, 4,   0x0f );     // reserved
-        bits_write( &bits, 8,   0xff );     // ODProfile (no ODcapability )
-        bits_write( &bits, 8,   0xff );     // sceneProfile
-        bits_write( &bits, 8,   0xfe );     // audioProfile (unspecified)
-        bits_write( &bits, 8,   0xfe );     // visualProfile( // )
-        bits_write( &bits, 8,   0xff );     // graphicProfile (no )
+            GetDescriptorLength24b( 0 ) );  /* variable length (fixed later) */
+        bits_write( &bits, 10,  0x01 );     /* ObjectDescriptorID */
+        bits_write( &bits, 1,   0x00 );     /* URL Flag */
+        bits_write( &bits, 1,   0x00 );     /* includeInlineProfileLevelFlag */
+        bits_write( &bits, 4,   0x0f );     /* reserved */
+        bits_write( &bits, 8,   0xff );     /* ODProfile (no ODcapability ) */
+        bits_write( &bits, 8,   0xff );     /* sceneProfile */
+        bits_write( &bits, 8,   0xfe );     /* audioProfile (unspecified) */
+        bits_write( &bits, 8,   0xfe );     /* visualProfile( // ) */
+        bits_write( &bits, 8,   0xff );     /* graphicProfile (no ) */
         for( i_stream = 0; i_stream < p_mux->i_nb_inputs; i_stream++ )
         {
             ts_stream_t *p_stream;
@@ -1936,41 +1958,41 @@ static void GetPMT( sout_mux_t *p_mux,
                 bits_buffer_t bits_fix_ESDescr, bits_fix_Decoder;
                 /* ES descriptor */
                 bits_align( &bits );
-                bits_write( &bits, 8,   0x03 );     // ES_DescrTag
+                bits_write( &bits, 8,   0x03 );     /* ES_DescrTag */
                 bits_fix_ESDescr = bits;
                 bits_write( &bits, 24,
-                            GetDescriptorLength24b( 0 ) ); // variable size
-                bits_write( &bits, 16,  p_stream->i_es_id );
-                bits_write( &bits, 1,   0x00 );     // streamDependency
-                bits_write( &bits, 1,   0x00 );     // URL Flag
-                bits_write( &bits, 1,   0x00 );     // OCRStreamFlag
-                bits_write( &bits, 5,   0x1f );     // streamPriority
-
-                // DecoderConfigDesciptor
+                            GetDescriptorLength24b( 0 ) ); /* variable size */
+                bits_write( &bits, 16,  p_stream->i_es_id ); 
+                bits_write( &bits, 1,   0x00 );     /* streamDependency */
+                bits_write( &bits, 1,   0x00 );     /* URL Flag */
+                bits_write( &bits, 1,   0x00 );     /* OCRStreamFlag */
+                bits_write( &bits, 5,   0x1f );     /* streamPriority */
+
+                /* DecoderConfigDesciptor */
                 bits_align( &bits );
-                bits_write( &bits, 8,   0x04 ); // DecoderConfigDescrTag
+                bits_write( &bits, 8,   0x04 ); /* DecoderConfigDescrTag */
                 bits_fix_Decoder = bits;
                 bits_write( &bits, 24,  GetDescriptorLength24b( 0 ) );
                 if( p_stream->i_stream_type == 0x10 )
                 {
-                    bits_write( &bits, 8, 0x20 );   // Visual 14496-2
-                    bits_write( &bits, 6, 0x04 );   // VisualStream
+                    bits_write( &bits, 8, 0x20 );   /* Visual 14496-2 */
+                    bits_write( &bits, 6, 0x04 );   /* VisualStream */
                 }
                 else if( p_stream->i_stream_type == 0x1b )
                 {
-                    bits_write( &bits, 8, 0x21 );   // Visual 14496-2
-                    bits_write( &bits, 6, 0x04 );   // VisualStream
+                    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 )
                 {
-                    bits_write( &bits, 8, 0x40 );   // Audio 14496-3
-                    bits_write( &bits, 6, 0x05 );   // AudioStream
+                    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') )
                 {
-                    bits_write( &bits, 8, 0x0B );   // Text Stream
-                    bits_write( &bits, 6, 0x04 );   // VisualStream
+                    bits_write( &bits, 8, 0x0B );   /* Text Stream */
+                    bits_write( &bits, 6, 0x04 );   /* VisualStream */
                 }
                 else
                 {
@@ -1980,18 +2002,18 @@ static void GetPMT( sout_mux_t *p_mux,
                     msg_Err( p_mux->p_sout,"Unsupported stream_type => "
                              "broken IOD" );
                 }
-                bits_write( &bits, 1,   0x00 );     // UpStream
-                bits_write( &bits, 1,   0x01 );     // reserved
-                bits_write( &bits, 24,  1024 * 1024 );  // bufferSizeDB
-                bits_write( &bits, 32,  0x7fffffff );   // maxBitrate
-                bits_write( &bits, 32,  0 );            // avgBitrate
+                bits_write( &bits, 1,   0x00 );         /* UpStream */
+                bits_write( &bits, 1,   0x01 );         /* reserved */
+                bits_write( &bits, 24,  1024 * 1024 );  /* bufferSizeDB */
+                bits_write( &bits, 32,  0x7fffffff );   /* maxBitrate */
+                bits_write( &bits, 32,  0 );            /* avgBitrate */
 
                 if( p_stream->i_decoder_specific_info > 0 )
                 {
                     int i;
-                    // DecoderSpecificInfo
+                    /* DecoderSpecificInfo */
                     bits_align( &bits );
-                    bits_write( &bits, 8,   0x05 ); // tag
+                    bits_write( &bits, 8,   0x05 ); /* tag */
                     bits_write( &bits, 24, GetDescriptorLength24b(
                                 p_stream->i_decoder_specific_info ) );
                     for( i = 0; i < p_stream->i_decoder_specific_info; i++ )
@@ -2005,15 +2027,15 @@ static void GetPMT( sout_mux_t *p_mux,
                             GetDescriptorLength24b( bits.i_data -
                             bits_fix_Decoder.i_data - 3 ) );
 
-                /* SLConfigDescriptor : predifined (0x01) */
+                /* SLConfigDescriptor : predefined (0x01) */
                 bits_align( &bits );
-                bits_write( &bits, 8,   0x06 ); // tag
+                bits_write( &bits, 8,   0x06 ); /* tag */
                 bits_write( &bits, 24,  GetDescriptorLength24b( 8 ) );
-                bits_write( &bits, 8,   0x01 ); // predefined
-                bits_write( &bits, 1,   0 );   // durationFlag
-                bits_write( &bits, 32,  0 );   // OCRResolution
-                bits_write( &bits, 8,   0 );   // OCRLength
-                bits_write( &bits, 8,   0 );   // InstantBitrateLength
+                bits_write( &bits, 8,   0x01 );/* predefined */
+                bits_write( &bits, 1,   0 );   /* durationFlag */
+                bits_write( &bits, 32,  0 );   /* OCRResolution */
+                bits_write( &bits, 8,   0 );   /* OCRLength */
+                bits_write( &bits, 8,   0 );   /* InstantBitrateLength */
                 bits_align( &bits );
 
                 /* fix ESDescr length */