]> git.sesse.net Git - vlc/blobdiff - modules/demux/ts.c
prepare release. We still need to update the Changelog
[vlc] / modules / demux / ts.c
index 1df67670e75abb5f3b5b3a23a1bb5e431bd6653f..bd13ff8fd688767989f842cc683af85620891cb1 100644 (file)
@@ -25,6 +25,7 @@
  * Preamble
  *****************************************************************************/
 #include <stdlib.h>                                      /* malloc(), free() */
+#include <ctype.h>
 
 #include <vlc/vlc.h>
 #include <vlc/input.h>
@@ -102,7 +103,7 @@ static void Close ( vlc_object_t * );
 
 vlc_module_begin();
     set_description( _("MPEG Transport Stream demuxer") );
-    set_shortname ( _("MPEG-TS") );
+    set_shortname ( "MPEG-TS" );
     set_category( CAT_INPUT );
     set_subcategory( SUBCAT_INPUT_DEMUX );
 
@@ -216,14 +217,6 @@ typedef struct
 
 } ts_prg_psi_t;
 
-typedef struct
-{
-    demux_t *p_demux;   /* Hack */
-    int i_table_id;
-    int i_version;
-    int i_service_id;
-} ts_eit_psi_t;
-
 typedef struct
 {
     /* for special PAT/SDT case */
@@ -235,10 +228,6 @@ typedef struct
     int             i_prg;
     ts_prg_psi_t    **prg;
 
-    /* For EIT */
-    int             i_eit;
-    ts_eit_psi_t    **eit;
-
 } ts_psi_t;
 
 typedef struct
@@ -442,11 +431,13 @@ static int Open( vlc_object_t *p_this )
         ts_pid_t *eit = &p_sys->pid[0x12];
 
         PIDInit( sdt, VLC_TRUE, NULL );
-        sdt->psi->handle = dvbpsi_AttachDemux( (dvbpsi_demux_new_cb_t)PSINewTableCallBack,
-                                               p_demux );
+        sdt->psi->handle =
+            dvbpsi_AttachDemux( (dvbpsi_demux_new_cb_t)PSINewTableCallBack,
+                                p_demux );
         PIDInit( eit, VLC_TRUE, NULL );
-        eit->psi->handle = dvbpsi_AttachDemux( (dvbpsi_demux_new_cb_t)PSINewTableCallBack,
-                                               p_demux );
+        eit->psi->handle =
+            dvbpsi_AttachDemux( (dvbpsi_demux_new_cb_t)PSINewTableCallBack,
+                                p_demux );
         if( p_sys->b_dvb_control )
         {
             stream_Control( p_demux->s, STREAM_CONTROL_ACCESS,
@@ -644,7 +635,6 @@ static void Close( vlc_object_t *p_this )
 
         if( pid->b_valid && pid->psi )
         {
-            int j;
             switch( pid->i_pid )
             {
                 case 0: /* PAT */
@@ -655,17 +645,8 @@ static void Close( vlc_object_t *p_this )
                     free( pid->psi );
                     break;
                 case 0x11: /* SDT */
-                    dvbpsi_DetachDemux( pid->psi->handle );
-                    free( pid->psi );
-                    break;
                 case 0x12: /* EIT */
                     dvbpsi_DetachDemux( pid->psi->handle );
-                    for( j = 0; j < pid->psi->i_eit; j++ )
-                    {
-                        free( pid->psi->eit[j] );
-                    }
-                    if( pid->psi->i_eit )
-                        free( pid->psi->eit );
                     free( pid->psi );
                     break;
                 default:
@@ -1058,8 +1039,6 @@ static void PIDInit( ts_pid_t *pid, vlc_bool_t b_psi, ts_psi_t *p_owner )
             pid->psi->handle= NULL;
             pid->psi->i_prg = 0;
             pid->psi->prg   = NULL;
-            pid->psi->i_eit = 0;
-            pid->psi->eit   = NULL;
         }
         pid->psi->i_pat_version  = -1;
         pid->psi->i_sdt_version  = -1;
@@ -1424,6 +1403,8 @@ static vlc_bool_t GatherPES( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk )
     {
         msg_Dbg( p_demux, "transport_error_indicator set (pid=%d)",
                  pid->i_pid );
+        if( pid->es->p_pes ) //&& pid->es->fmt.i_cat == VIDEO_ES )
+            pid->es->p_pes->i_flags |= BLOCK_FLAG_CORRUPTED;
     }
 
     if( p_demux->p_sys->csa )
@@ -2034,18 +2015,21 @@ static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt )
         return;
     }
 
-    msg_Dbg( p_demux, "new SDT ts_id=%d version=%d current_next=%d network_id=%d",
-             p_sdt->i_ts_id, p_sdt->i_version, p_sdt->b_current_next, p_sdt->i_network_id );
+    msg_Dbg( p_demux, "new SDT ts_id=%d version=%d current_next=%d "
+             "network_id=%d",
+             p_sdt->i_ts_id, p_sdt->i_version, p_sdt->b_current_next,
+             p_sdt->i_network_id );
 
     for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next )
     {
         vlc_meta_t          *p_meta = vlc_meta_New();
         dvbpsi_descriptor_t *p_dr;
 
-        msg_Dbg( p_demux, "  * service id=%d eit schedule=%d present=%d runing=%d free_ca=%d",
-                p_srv->i_service_id,
-                p_srv->b_eit_schedule, p_srv->b_eit_present, p_srv->i_running_status,
-                p_srv->b_free_ca );
+        msg_Dbg( p_demux, "  * service id=%d eit schedule=%d present=%d "
+                 "runing=%d free_ca=%d",
+                 p_srv->i_service_id, p_srv->b_eit_schedule,
+                 p_srv->b_eit_present, p_srv->i_running_status,
+                 p_srv->b_free_ca );
 
         for( p_dr = p_srv->p_first_descriptor; p_dr; p_dr = p_dr->p_next )
         {
@@ -2074,7 +2058,8 @@ static void SDTCallBack( demux_t *p_demux, dvbpsi_sdt_t *p_sdt )
                 char str1[257];
                 char str2[257];
 
-                memcpy( str1, pD->i_service_provider_name, pD->i_service_provider_name_length );
+                memcpy( str1, pD->i_service_provider_name,
+                        pD->i_service_provider_name_length );
                 str1[pD->i_service_provider_name_length] = '\0';
                 memcpy( str2, pD->i_service_name, pD->i_service_name_length );
                 str2[pD->i_service_name_length] = '\0';
@@ -2129,29 +2114,39 @@ static void DecodeMjd( int i_mjd, int *p_y, int *p_m, int *p_d )
     }
 }
 #endif
-
-static void EITCallBack( ts_eit_psi_t *psi, dvbpsi_eit_t *p_eit )
+static void EITEventFixString( unsigned char *psz )
+{
+    int i_len;
+    /* Sometimes the first char isn't a normal char but designed
+     * caracters encoding, for now lets skip it */
+    if( psz[0] >= 0x20 )
+            return;
+    if( ( i_len = strlen( psz ) ) > 0 )
+        memmove( &psz[0], &psz[1], i_len ); /* Copy the \0 too */
+}
+static void EITCallBack( demux_t *p_demux, dvbpsi_eit_t *p_eit )
 {
-    demux_t              *p_demux = psi->p_demux;
-
     dvbpsi_eit_event_t *p_evt;
+    vlc_meta_t         *p_meta;
+    vlc_bool_t b_event_active = VLC_FALSE;
 
     msg_Dbg( p_demux, "EITCallBack called" );
-    if( psi->i_version != -1 &&
-        ( !p_eit->b_current_next || psi->i_version == p_eit->i_version ) )
+    if( !p_eit->b_current_next )
     {
         dvbpsi_DeleteEIT( p_eit );
         return;
     }
 
-    msg_Dbg( p_demux, "new EIT service_id=%d version=%d current_next=%d ts_id=%d network_id=%d"
-                      "segment_last_section_number=%d last_table_id=%d",
-             p_eit->i_service_id, p_eit->i_version, p_eit->b_current_next, p_eit->i_ts_id,
-             p_eit->i_network_id, p_eit->i_segment_last_section_number, p_eit->i_last_table_id );
+    msg_Dbg( p_demux, "new EIT service_id=%d version=%d current_next=%d "
+             "ts_id=%d network_id=%d segment_last_section_number=%d "
+             "last_table_id=%d",
+             p_eit->i_service_id, p_eit->i_version, p_eit->b_current_next,
+             p_eit->i_ts_id, p_eit->i_network_id,
+             p_eit->i_segment_last_section_number, p_eit->i_last_table_id );
 
+    p_meta = vlc_meta_New();
     for( p_evt = p_eit->p_first_event; p_evt; p_evt = p_evt->p_next )
     {
-        vlc_meta_t          *p_meta = vlc_meta_New();
         dvbpsi_descriptor_t *p_dr;
         char                *psz_cat = malloc( strlen("Event")+10 );
         char                psz_start[15];
@@ -2195,6 +2190,8 @@ static void EITCallBack( ts_eit_psi_t *psi, dvbpsi_eit_t *p_eit )
                     memcpy( psz_text, pE->i_text, pE->i_text_length );
                     psz_text[pE->i_text_length] = '\0';
 
+                    EITEventFixString(psz_name);
+                    EITEventFixString(psz_text);
                     msg_Dbg( p_demux, "    - short event lang=%3.3s '%s' : '%s'",
                              pE->i_iso_639_code, psz_name, psz_text );
                 }
@@ -2215,10 +2212,12 @@ static void EITCallBack( ts_eit_psi_t *psi, dvbpsi_eit_t *p_eit )
                         memcpy( str1, pE->i_item_description[i],
                                 pE->i_item_description_length[i] );
                         str1[pE->i_item_description_length[i]] = '\0';
+                        EITEventFixString(str1);
 
-                        memcpy( str1, pE->i_item[i],
+                        memcpy( str2, pE->i_item[i],
                                 pE->i_item_length[i] );
                         str2[pE->i_item_length[i]] = '\0';
+                        EITEventFixString(str2);
 
                         msg_Dbg( p_demux, "       - desc='%s' item='%s'", str1, str2 );
                         psz_extra = realloc( psz_extra,
@@ -2232,6 +2231,8 @@ static void EITCallBack( ts_eit_psi_t *psi, dvbpsi_eit_t *p_eit )
 
                     memcpy( str1, pE->i_text, pE->i_text_length );
                     str1[pE->i_text_length] = '\0';
+                    EITEventFixString(str1);
+
                     msg_Dbg( p_demux, "       - text='%s'", str1 );
                     psz_extra = realloc( psz_extra,
                                          strlen(psz_extra) + strlen(str1) + 2 );
@@ -2253,14 +2254,22 @@ static void EITCallBack( ts_eit_psi_t *psi, dvbpsi_eit_t *p_eit )
         vlc_meta_Add( p_meta, psz_cat, psz_value );
         free( psz_value );
 
-        es_out_Control( p_demux->out, ES_OUT_SET_GROUP_META,
-                        p_eit->i_service_id, p_meta );
-        vlc_meta_Delete( p_meta );
+        if( p_evt->i_running_status == 0x04 )
+        {
+            vlc_meta_Add( p_meta, VLC_META_NOW_PLAYING, psz_name );
+            b_event_active = VLC_TRUE;
+        }
 
         free( psz_cat );
         free( psz_extra );
     }
-    psi->i_version = p_eit->i_version;
+
+    if( !b_event_active )
+        vlc_meta_Add( p_meta, VLC_META_NOW_PLAYING, "" );
+    es_out_Control( p_demux->out, ES_OUT_SET_GROUP_META,
+                    p_eit->i_service_id, p_meta );
+    vlc_meta_Delete( p_meta );
+
     dvbpsi_DeleteEIT( p_eit );
 }
 
@@ -2271,27 +2280,23 @@ static void PSINewTableCallBack( demux_t *p_demux, dvbpsi_handle h,
     msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)",
              i_table_id, i_table_id, i_extension, i_extension );
 #endif
+
     if( i_table_id == 0x42 )
     {
         msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)",
                  i_table_id, i_table_id, i_extension, i_extension );
 
-        dvbpsi_AttachSDT( h, i_table_id, i_extension, (dvbpsi_sdt_callback)SDTCallBack, p_demux );
+        dvbpsi_AttachSDT( h, i_table_id, i_extension,
+                          (dvbpsi_sdt_callback)SDTCallBack, p_demux );
     }
-    else if( i_table_id == 0x4e ||                          /* Current/Following */
+    else if( i_table_id == 0x4e || /* Current/Following */
              ( i_table_id >= 0x50 && i_table_id <= 0x5f ) ) /* Schedule */
     {
-        ts_eit_psi_t *psi = malloc( sizeof(ts_eit_psi_t) );
-
         msg_Dbg( p_demux, "PSINewTableCallBack: table 0x%x(%d) ext=0x%x(%d)",
                  i_table_id, i_table_id, i_extension, i_extension );
 
-        psi->p_demux = p_demux;
-        psi->i_table_id = i_table_id;
-        psi->i_version = -1;
-        psi->i_service_id = i_extension;
-
-        dvbpsi_AttachEIT( h, i_table_id, i_extension, (dvbpsi_eit_callback)EITCallBack, psi );
+        dvbpsi_AttachEIT( h, i_table_id, i_extension,
+                          (dvbpsi_eit_callback)EITCallBack, p_demux );
     }
 }
 #endif
@@ -2415,9 +2420,22 @@ static void PMTCallBack( demux_t *p_demux, dvbpsi_pmt_t *p_pmt )
 
         if( !old_pid && p_sys->pid[p_es->i_pid].b_valid )
         {
-            msg_Warn( p_demux, "pmt error: pid=%d already defined",
-                      p_es->i_pid );
-            continue;
+            ts_pid_t *pid = &p_sys->pid[p_es->i_pid];
+            if( ( pid->i_pid == 0x11 /* SDT */ ||
+                  pid->i_pid == 0x12 /* EDT */ ) && pid->psi )
+            {
+                /* This doesn't look like a DVB stream so don't try
+                 * parsing the SDT/EDT */
+                dvbpsi_DetachDemux( pid->psi->handle );
+                free( pid->psi );
+                pid->psi = 0;
+            }
+            else
+            {
+                msg_Warn( p_demux, "pmt error: pid=%d already defined",
+                          p_es->i_pid );
+                continue;
+            }
         }
 
         PIDInit( pid, VLC_FALSE, pmt->psi );
@@ -2936,6 +2954,7 @@ static void PATCallBack( demux_t *p_demux, dvbpsi_pat_t *p_pat )
         /* Delete PMT pid */
         for( i = 0; i < i_pmt_rm; i++ )
         {
+            int i_prg;
             if( p_sys->b_dvb_control )
             {
                 if( stream_Control( p_demux->s, STREAM_CONTROL_ACCESS,
@@ -2944,6 +2963,13 @@ static void PATCallBack( demux_t *p_demux, dvbpsi_pat_t *p_pat )
                     p_sys->b_dvb_control = VLC_FALSE;
             }
 
+            for( i_prg = 0; i_prg < pmt_rm[i]->psi->i_prg; i_prg++ )
+            {
+                const int i_number = pmt_rm[i]->psi->prg[i_prg]->i_number;
+                if( i_number != 0 )
+                    es_out_Control( p_demux->out, ES_OUT_DEL_GROUP, i_number );
+            }
+
             PIDClean( p_demux->out, &p_sys->pid[pmt_rm[i]->i_pid] );
             TAB_REMOVE( p_sys->i_pmt, p_sys->pmt, pmt_rm[i] );
         }