]> git.sesse.net Git - vlc/blobdiff - modules/mux/mpeg/ts.c
Merge branch 'master' of git@git.videolan.org:vlc
[vlc] / modules / mux / mpeg / ts.c
index 4b118005ce2349af8d1e8c52bba6cd0078c206b6..99bdcfd3e587edf6a39dc188f5ac936f39080b80 100644 (file)
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
-#include <stdlib.h>
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
 
 #include <vlc/vlc.h>
 #include <vlc_sout.h>
@@ -157,10 +160,9 @@ static void    Close  ( vlc_object_t * );
   "16 char string (8 hexadecimal bytes).")
 
 #define CPKT_TEXT N_("Packet size in bytes to encrypt")
-/// \bug [String] Extra space
 #define CPKT_LONGTEXT N_("Size of the TS packet to encrypt. " \
     "The encryption routines subtract the TS-header from the value before " \
-    "encrypting. " )
+    "encrypting." )
 
 #define SOUT_CFG_PREFIX "sout-ts-"
 #ifdef HAVE_BSEARCH
@@ -305,8 +307,7 @@ static inline block_t *BufferChainPeek( sout_buffer_chain_t *c )
     return b;
 }
 
-static inline void BufferChainClean( sout_instance_t *p_sout,
-                                     sout_buffer_chain_t *c )
+static inline void BufferChainClean( sout_buffer_chain_t *c )
 {
     block_t *b;
 
@@ -855,29 +856,30 @@ static void Close( vlc_object_t * p_this )
  *****************************************************************************/
 static int Control( sout_mux_t *p_mux, int i_query, va_list args )
 {
+    VLC_UNUSED(p_mux);
     vlc_bool_t *pb_bool;
     char **ppsz;
 
-   switch( i_query )
-   {
-       case MUX_CAN_ADD_STREAM_WHILE_MUXING:
-           pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
-           *pb_bool = VLC_TRUE;
-           return VLC_SUCCESS;
+    switch( i_query )
+    {
+        case MUX_CAN_ADD_STREAM_WHILE_MUXING:
+            pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
+            *pb_bool = VLC_TRUE;
+            return VLC_SUCCESS;
 
-       case MUX_GET_ADD_STREAM_WAIT:
-           pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
-           *pb_bool = VLC_FALSE;
-           return VLC_SUCCESS;
+        case MUX_GET_ADD_STREAM_WAIT:
+            pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
+            *pb_bool = VLC_FALSE;
+            return VLC_SUCCESS;
 
-       case MUX_GET_MIME:
-           ppsz = (char**)va_arg( args, char ** );
-           *ppsz = strdup( "video/mpeg" );  /* FIXME not sure */
-           return VLC_SUCCESS;
+        case MUX_GET_MIME:
+            ppsz = (char**)va_arg( args, char ** );
+            *ppsz = strdup( "video/mpeg" );  /* FIXME not sure */
+            return VLC_SUCCESS;
 
         default:
             return VLC_EGENERIC;
-   }
+    }
 }
 
 /*****************************************************************************
@@ -890,6 +892,8 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
     int                  i;
 
     p_input->p_sys = p_stream = malloc( sizeof( ts_stream_t ) );
+    if( !p_input->p_sys )
+        return VLC_ENOMEM;
 
     /* Init this new stream */
     if ( p_sys->b_es_id_pid )
@@ -954,6 +958,7 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
             switch( p_input->p_fmt->i_codec )
             {
                 case VLC_FOURCC( 'm', 'p','g', 'a' ):
+                case VLC_FOURCC( 'm', 'p', '3', ' ' ):
                     p_stream->i_stream_type =
                         p_input->p_fmt->audio.i_rate >= 32000 ? 0x03 : 0x04;
                     p_stream->i_stream_id = 0xc0;
@@ -1018,6 +1023,12 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
 
     p_stream->i_langs = 1+p_input->p_fmt->i_extra_languages;
     p_stream->lang = malloc(p_stream->i_langs*3);
+    if( !p_stream->lang )
+    {
+        p_stream->i_langs = 0;
+        free( p_stream );
+        return VLC_ENOMEM;
+    }
     i = 1;
     p_stream->lang[0] =
     p_stream->lang[1] =
@@ -1055,7 +1066,7 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
         {
             char *psz = p_input->p_fmt->p_extra_languages[i-1].psz_language;
             const iso639_lang_t *pl = NULL;
-            
+
             if( strlen( psz ) == 2 )
             {
                 pl = GetLang_1( psz );
@@ -1073,7 +1084,7 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
                 p_stream->lang[i*3+0] = pl->psz_iso639_2T[0];
                 p_stream->lang[i*3+1] = pl->psz_iso639_2T[1];
                 p_stream->lang[i*3+2] = pl->psz_iso639_2T[2];
-                
                 msg_Dbg( p_mux, "    - lang=%c%c%c",
                          p_stream->lang[i*3+0], p_stream->lang[i*3+1],
                          p_stream->lang[i*3+2] );
@@ -1082,17 +1093,6 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
         i++;
     }
 
-    /* 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 )
-    {
-        p_stream->p_decoder_specific_info =
-            malloc( p_stream->i_decoder_specific_info );
-        memcpy( p_stream->p_decoder_specific_info,
-                p_input->p_fmt->p_extra,
-                p_input->p_fmt->i_extra );
-    }
-
     /* Create decoder specific info for subt */
     if( p_stream->i_codec == VLC_FOURCC( 's', 'u','b', 't' ) )
     {
@@ -1101,44 +1101,64 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
         p_stream->i_decoder_specific_info = 55;
         p_stream->p_decoder_specific_info = p =
             malloc( p_stream->i_decoder_specific_info );
-
-        p[0] = 0x10;    /* textFormat, 0x10 for 3GPP TS 26.245 */
-        p[1] = 0x00;    /* flags: 1b: associated video info flag
-                                  3b: reserved
-                                  1b: duration flag
-                                  3b: reserved */
-        p[2] = 52;      /* remaining size */
-
-        p += 3;
-
-        p[0] = p[1] = p[2] = p[3] = 0; p+=4;    /* display flags */
-        *p++ = 0;  /* horizontal justification (-1: left, 0 center, 1 right) */
-        *p++ = 1;  /* vertical   justification (-1: top, 0 center, 1 bottom) */
-
-        p[0] = p[1] = p[2] = 0x00; p+=3;/* background rgb */
-        *p++ = 0xff;                    /* background a */
-
-        p[0] = p[1] = 0; p += 2;        /* text box top */
-        p[0] = p[1] = 0; p += 2;        /* text box left */
-        p[0] = p[1] = 0; p += 2;        /* text box bottom */
-        p[0] = p[1] = 0; p += 2;        /* text box right */
-
-        p[0] = p[1] = 0; p += 2;        /* start char */
-        p[0] = p[1] = 0; p += 2;        /* end char */
-        p[0] = p[1] = 0; p += 2;        /* default font id */
-
-        *p++ = 0;                       /* font style flags */
-        *p++ = 12;                      /* font size */
-
-        p[0] = p[1] = p[2] = 0x00; p+=3;/* foreground rgb */
-        *p++ = 0x00;                    /* foreground a */
-
-        p[0] = p[1] = p[2] = 0; p[3] = 22; p += 4;
-        memcpy( p, "ftab", 4 ); p += 4;
-        *p++ = 0; *p++ = 1;             /* entry count */
-        p[0] = p[1] = 0; p += 2;        /* font id */
-        *p++ = 9;                       /* font name length */
-        memcpy( p, "Helvetica", 9 );    /* font name */
+        if( p )
+        {
+            p[0] = 0x10;    /* textFormat, 0x10 for 3GPP TS 26.245 */
+            p[1] = 0x00;    /* flags: 1b: associated video info flag
+                                    3b: reserved
+                                    1b: duration flag
+                                    3b: reserved */
+            p[2] = 52;      /* remaining size */
+
+            p += 3;
+
+            p[0] = p[1] = p[2] = p[3] = 0; p+=4;    /* display flags */
+            *p++ = 0;  /* horizontal justification (-1: left, 0 center, 1 right) */
+            *p++ = 1;  /* vertical   justification (-1: top, 0 center, 1 bottom) */
+
+            p[0] = p[1] = p[2] = 0x00; p+=3;/* background rgb */
+            *p++ = 0xff;                    /* background a */
+
+            p[0] = p[1] = 0; p += 2;        /* text box top */
+            p[0] = p[1] = 0; p += 2;        /* text box left */
+            p[0] = p[1] = 0; p += 2;        /* text box bottom */
+            p[0] = p[1] = 0; p += 2;        /* text box right */
+
+            p[0] = p[1] = 0; p += 2;        /* start char */
+            p[0] = p[1] = 0; p += 2;        /* end char */
+            p[0] = p[1] = 0; p += 2;        /* default font id */
+
+            *p++ = 0;                       /* font style flags */
+            *p++ = 12;                      /* font size */
+
+            p[0] = p[1] = p[2] = 0x00; p+=3;/* foreground rgb */
+            *p++ = 0x00;                    /* foreground a */
+
+            p[0] = p[1] = p[2] = 0; p[3] = 22; p += 4;
+            memcpy( p, "ftab", 4 ); p += 4;
+            *p++ = 0; *p++ = 1;             /* entry count */
+            p[0] = p[1] = 0; p += 2;        /* font id */
+            *p++ = 9;                       /* font name length */
+            memcpy( p, "Helvetica", 9 );    /* font name */
+        }
+        else p_stream->i_decoder_specific_info = 0;
+    }
+    else
+    {
+        /* 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 )
+        {
+            p_stream->p_decoder_specific_info =
+                malloc( p_stream->i_decoder_specific_info );
+            if( p_stream->p_decoder_specific_info )
+            {
+                memcpy( p_stream->p_decoder_specific_info,
+                        p_input->p_fmt->p_extra,
+                        p_input->p_fmt->i_extra );
+            }
+            else p_stream->i_decoder_specific_info = 0;
+        }
     }
 
     /* Init pes chain */
@@ -1219,7 +1239,7 @@ static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
     }
 
     /* Empty all data in chain_pes */
-    BufferChainClean( p_mux->p_sout, &p_stream->chain_pes );
+    BufferChainClean( &p_stream->chain_pes );
 
     if( p_stream->lang )
     {
@@ -1338,26 +1358,26 @@ static int Mux( sout_mux_t *p_mux )
                     p_input = p_mux->pp_inputs[i];
                 p_stream = (ts_stream_t*)p_input->p_sys;
 
-                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 )
+                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 ) )
                 {
                     /* Need more data */
-                    if( p_input->p_fifo->i_depth <= 1 )
+                    if( block_FifoCount( p_input->p_fifo ) <= 1 )
                     {
-                        if( p_input->p_fmt->i_cat == AUDIO_ES ||
-                            p_input->p_fmt->i_cat == VIDEO_ES )
+                        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 )
+                        else if( block_FifoCount( p_input->p_fifo ) <= 0 )
                         {
                             /* spu, only one packet is needed */
                             continue;
                         }
-                        else
+                        else if( p_input->p_fmt->i_cat == SPU_ES )
                         {
                             /* Don't mux the SPU yet if it is too early */
                             block_t *p_spu = block_FifoShow( p_input->p_fifo );
@@ -1365,15 +1385,14 @@ static int Mux( sout_mux_t *p_mux )
                             i_spu_delay =
                                 p_spu->i_dts - p_pcr_stream->i_pes_dts;
 
-                            if( i_spu_delay > i_shaping_delay &&
-                                i_spu_delay < I64C(100000000) )
+                            if( ( i_spu_delay > i_shaping_delay ) &&
+                                ( i_spu_delay < I64C(100000000) ) )
                                 continue;
 
-                            if ( i_spu_delay >= I64C(100000000)
-                                  || i_spu_delay < 10000 )
+                            if ( ( i_spu_delay >= I64C(100000000) ) ||
+                                 ( i_spu_delay < I64C(10000) ) )
                             {
-                                BufferChainClean( p_mux->p_sout,
-                                                  &p_stream->chain_pes );
+                                BufferChainClean( &p_stream->chain_pes );
                                 p_stream->i_pes_dts = 0;
                                 p_stream->i_pes_used = 0;
                                 p_stream->i_pes_length = 0;
@@ -1390,7 +1409,7 @@ static int Mux( sout_mux_t *p_mux )
                     else
                         p_data = FixPES( p_mux, p_input->p_fifo );
 
-                    if( p_input->p_fifo->i_depth > 0 &&
+                    if( block_FifoCount( p_input->p_fifo ) > 0 &&
                         p_input->p_fmt->i_cat != SPU_ES )
                     {
                         block_t *p_next = block_FifoShow( p_input->p_fifo );
@@ -1415,16 +1434,14 @@ static int Mux( sout_mux_t *p_mux )
                                   p_pcr_stream->i_pes_dts );
                         block_Release( p_data );
 
-                        BufferChainClean( p_mux->p_sout,
-                                          &p_stream->chain_pes );
+                        BufferChainClean( &p_stream->chain_pes );
                         p_stream->i_pes_dts = 0;
                         p_stream->i_pes_used = 0;
                         p_stream->i_pes_length = 0;
 
                         if( p_input->p_fmt->i_cat != SPU_ES )
                         {
-                            BufferChainClean( p_mux->p_sout,
-                                              &p_pcr_stream->chain_pes );
+                            BufferChainClean( &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;
@@ -1482,6 +1499,12 @@ static int Mux( sout_mux_t *p_mux )
                                 i_header_size = 0x24;
                                 b_data_alignment = 1;
                             }
+                            else if( p_input->p_fmt->i_codec ==
+                                       VLC_FOURCC('d','v','b','s') )
+                            {
+                                /* EN 300 743 */
+                                b_data_alignment = 1;
+                            }
                         }
                         else if( p_data->i_length < 0 ||
                                  p_data->i_length > 2000000 )
@@ -2207,21 +2230,33 @@ static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c )
 {
     sout_mux_sys_t  *p_sys = p_mux->p_sys;
     block_t   *p_pmt[MAX_PMT];
-    block_t   *p_sdt;
 
-    dvbpsi_sdt_t        sdt;
     dvbpsi_pmt_es_t     *p_es;
-    dvbpsi_psi_section_t *p_section[MAX_PMT], *p_section2;
-    dvbpsi_sdt_service_t *p_service;
-    char            *psz_sdt_desc;
-    int             i_pidinput;
+    dvbpsi_psi_section_t *p_section[MAX_PMT];
 
+    int             i_pidinput;
     int             i_stream;
     int             i;
     int             *p_usepid = NULL;
 
+#ifdef HAVE_DVBPSI_SDT
+    block_t         *p_sdt;
+    dvbpsi_sdt_t    sdt;
+
+    dvbpsi_psi_section_t* p_section2;
+    dvbpsi_sdt_service_t *p_service;
+
+    uint8_t         *psz_sdt_desc;
+#endif
+
     if( p_sys->dvbpmt == NULL )
+    {
         p_sys->dvbpmt = malloc( p_sys->i_num_pmt * sizeof(dvbpsi_pmt_t) );
+        if( !p_sys->dvbpmt )
+        {
+            return;
+        }
+    }
 #ifdef HAVE_DVBPSI_SDT
     if( p_sys->b_sdt )
         dvbpsi_InitSDT( &sdt, p_sys->i_tsid, 1, 1, p_sys->i_netid );
@@ -2249,26 +2284,30 @@ static void GetPMT( sout_mux_t *p_mux, sout_buffer_chain_t *c )
 #define psz_sdtserv p_sys->sdt_descriptors[i].psz_service_name
 
             /* FIXME: Ineffecient malloc's & ugly code......  */
-            if( psz_sdtprov != NULL && psz_sdtserv != NULL )
+            if( ( psz_sdtprov != NULL ) && ( psz_sdtserv != NULL ) )
             {
                 psz_sdt_desc = malloc( 3 + strlen(psz_sdtprov)
                                          + strlen(psz_sdtserv) );
-                psz_sdt_desc[0] = 0x01; /* digital television service */
-
-                /* service provider name length */
-                psz_sdt_desc[1] = (char)strlen(psz_sdtprov);
-                memcpy( &psz_sdt_desc[2], psz_sdtprov, strlen(psz_sdtprov) );
-
-                /* service name length */
-                psz_sdt_desc[ 2 + strlen(psz_sdtprov) ]
-                    = (char)strlen(psz_sdtserv);
-                memcpy( &psz_sdt_desc[3+strlen(psz_sdtprov)], psz_sdtserv,
-                        strlen(psz_sdtserv) );
-
-                dvbpsi_SDTServiceAddDescriptor( p_service, 0x48,
-                        3 + strlen(psz_sdtprov) + strlen(psz_sdtserv),
-                        psz_sdt_desc );
-                free( psz_sdt_desc );
+                if( psz_sdt_desc )
+                {
+                    psz_sdt_desc[0] = 0x01; /* digital television service */
+
+                    /* service provider name length */
+                    psz_sdt_desc[1] = (char)strlen(psz_sdtprov);
+                    memcpy( &psz_sdt_desc[2], psz_sdtprov, strlen(psz_sdtprov) );
+
+                    /* service name length */
+                    psz_sdt_desc[ 2 + strlen(psz_sdtprov) ]
+                        = (char)strlen(psz_sdtserv);
+                    memcpy( &psz_sdt_desc[3+strlen(psz_sdtprov)], psz_sdtserv,
+                            strlen(psz_sdtserv) );
+
+                    dvbpsi_SDTServiceAddDescriptor( p_service, 0x48,
+                            3 + strlen(psz_sdtprov) + strlen(psz_sdtserv),
+                            (uint8_t *)psz_sdt_desc );
+                    free( psz_sdt_desc );
+                    psz_sdt_desc = NULL;
+                }
             }
 #undef psz_sdtprov
 #undef psz_sdtserv