]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
mpegts: cat monitor - manage correctly EMM PID list
authorJaroslav Kysela <perex@perex.cz>
Sat, 18 Nov 2017 17:11:00 +0000 (18:11 +0100)
committerJaroslav Kysela <perex@perex.cz>
Mon, 20 Nov 2017 08:05:21 +0000 (09:05 +0100)
src/descrambler.h
src/input/mpegts.h
src/input/mpegts/dvb_psi.c
src/input/mpegts/mpegts_input.c
src/input/mpegts/tsdemux.c
src/service.c
src/streaming.c
src/tvheadend.h

index a887f56f3f4b8b3f0814b87d7d9423ddde9e068a..42528cb83384b0993a568f4855836a8945bc97ea 100644 (file)
@@ -145,14 +145,13 @@ typedef struct descrambler_table {
 /**
  * List of CA ids
  */
-#define CAID_REMOVE_ME ((uint16_t)-1)
-
 typedef struct caid {
   LIST_ENTRY(caid) link;
 
   uint16_t pid;
   uint16_t caid;
   uint32_t providerid;
+  uint8_t  delete_me;
   uint8_t  use;
   uint8_t  filter;
 
index 0c8c014be4cbcd50ae8ad3fb752443c490fb840c..a4ea64c4cbfb529bcfd5409896321aa970a0e566 100644 (file)
@@ -1008,7 +1008,7 @@ int mpegts_input_close_pid
 void mpegts_input_close_pids
   ( mpegts_input_t *mi, mpegts_mux_t *mm, void *owner, int all );
 
-int mpegts_input_open_service_pid
+elementary_stream_t *mpegts_input_open_service_pid
   ( mpegts_input_t *mi, mpegts_mux_t *mm, service_t *s,
     streaming_component_type_t stype, int pid, int weight, int create );
 
index e608096b62ebe73531ec8a868c9044c19e713cc0..c116747b60beda22c00710a95a60258d4f9a8168 100644 (file)
@@ -2197,6 +2197,7 @@ psi_desc_add_ca
       if (c->pid > 0 && c->pid != pid)
         r |= PMT_UPDATE_CAID_PID;
       c->pid = pid;
+      c->delete_me = 0;
 
       if(c->providerid != provid) {
         c->providerid = provid;
@@ -2212,6 +2213,8 @@ psi_desc_add_ca
   c->providerid = provid;
   c->use = 1;
   c->pid = pid;
+  c->delete_me = 0;
+  c->filter = 0;
   LIST_INSERT_HEAD(&st->es_caids, c, link);
   r |= PMT_UPDATE_NEW_CAID;
   return r;
@@ -2378,7 +2381,7 @@ psi_parse_pmt
     st->es_delete_me = 1;
 
     LIST_FOREACH(c, &st->es_caids, link)
-      c->pid = CAID_REMOVE_ME;
+      c->delete_me = 1;
   }
 
   // Common descriptors
@@ -2621,7 +2624,7 @@ psi_parse_pmt
 
     for(c = LIST_FIRST(&st->es_caids); c != NULL; c = cn) {
       cn = LIST_NEXT(c, link);
-      if (c->pid == CAID_REMOVE_ME) {
+      if (c->delete_me) {
         LIST_REMOVE(c, link);
         free(c);
         update |= PMT_UPDATE_CAID_DELETED;
index b0a0f25027c9c309b67520595935ef2f8572af86..dc3d745654606f9555e0be31b80a16a17ab993f3 100644 (file)
@@ -631,7 +631,7 @@ mpegts_input_close_pid
   return 0;
 }
 
-int
+elementary_stream_t *
 mpegts_input_open_service_pid
   ( mpegts_input_t *mi, mpegts_mux_t *mm,
     service_t *s, streaming_component_type_t stype,
@@ -644,7 +644,7 @@ mpegts_input_open_service_pid
   es = NULL;
   if (service_stream_find((service_t *)s, pid) == NULL) {
     if (!create)
-      return -1;
+      return NULL;
     es = service_stream_create(s, pid, stype);
     es->es_pid_opened = 1;
   }
@@ -652,7 +652,7 @@ mpegts_input_open_service_pid
     mpegts_input_open_pid(mi, mm, pid,
                           MPS_SERVICE, weight, s, 0);
   }
-  return 0;
+  return es;
 }
 
 static void
@@ -686,6 +686,8 @@ mpegts_input_cat_pass_callback
   mpegts_psi_table_state_t *st  = NULL;
   service_t                *s   = mt->mt_opaque;
   mpegts_input_t           *mi;
+  elementary_stream_t      *es, *next;
+  caid_t                   *c, *cn;
 
   /* Start */
   r = dvb_table_begin((mpegts_psi_table_t *)mt, ptr, len,
@@ -697,6 +699,19 @@ mpegts_input_cat_pass_callback
   /* Send CAT data for descramblers */
   descrambler_cat_data(mm, ptr, len);
 
+  mi = mm->mm_active ? mm->mm_active->mmi_input : NULL;
+  if (mi == NULL) goto fin;
+
+  pthread_mutex_lock(&mi->mi_output_lock);
+  pthread_mutex_lock(&s->s_stream_mutex);
+
+  TAILQ_FOREACH(es, &s->s_components, es_link) {
+    if (es->es_type != SCT_CAT) continue;
+    es->es_delete_me = 1;
+    LIST_FOREACH(c, &es->es_caids, link)
+      c->delete_me = 1;
+  }
+
   while(len > 2) {
     dtag = *ptr++;
     dlen = *ptr++;
@@ -709,13 +724,28 @@ mpegts_input_cat_pass_callback
           pid  = ((ptr[2] & 0x1f) << 8) | ptr[3];
           tvhdebug(LS_TBL_BASE, "cat:  pass: caid %04X (%d) pid %04X (%d)",
                    (uint16_t)caid, (uint16_t)caid, pid, pid);
-          mi = mm->mm_active ? mm->mm_active->mmi_input : NULL;
-          if (mi) {
-            pthread_mutex_lock(&mi->mi_output_lock);
-            pthread_mutex_lock(&s->s_stream_mutex);
-            mpegts_input_open_service_pid(mi, mm, s, SCT_CA, pid, MPS_WEIGHT_CAT, 1);
-            pthread_mutex_unlock(&s->s_stream_mutex);
-            pthread_mutex_unlock(&mi->mi_output_lock);
+          es = mpegts_input_open_service_pid(mi, mm, s, SCT_CAT, pid,
+                                             MPS_WEIGHT_CAT, 1);
+          if (es) {
+            LIST_FOREACH(c, &es->es_caids, link) {
+              if (c->pid == pid) {
+                c->caid = caid;
+                c->delete_me = 0;
+                es->es_delete_me = 0;
+                break;
+              }
+            }
+            if (c == NULL) {
+              c = malloc(sizeof(caid_t));
+              c->caid = caid;
+              c->providerid = 0;
+              c->use = 1;
+              c->pid = pid;
+              c->delete_me = 0;
+              c->filter = 0;
+              LIST_INSERT_HEAD(&es->es_caids, c, link);
+              es->es_delete_me = 0;
+            }
           }
         }
         break;
@@ -727,7 +757,25 @@ mpegts_input_cat_pass_callback
     len -= dlen;
   }
 
+  for (es = TAILQ_FIRST(&s->s_components); es != NULL; es = next) {
+    next = TAILQ_NEXT(es, es_link);
+    if (es->es_type != SCT_CAT) continue;
+    for (c = LIST_FIRST(&es->es_caids); c != NULL; c = cn) {
+      cn = LIST_NEXT(c, link);
+      if (cn->delete_me) {
+        LIST_REMOVE(c, link);
+        free(c);
+      }
+      if (es->es_delete_me)
+        service_stream_destroy(s, es);
+    }
+  }
+
+  pthread_mutex_unlock(&s->s_stream_mutex);
+  pthread_mutex_unlock(&mi->mi_output_lock);
+
   /* Finish */
+fin:
   return dvb_table_end((mpegts_psi_table_t *)mt, st, sect);
 }
 
index eb75ed5608901c8d8ca7367225c5a2ed939f451d..d4d0191db024be27ead4aeef7707278e2d35bca2 100644 (file)
@@ -192,7 +192,7 @@ ts_recv_packet0
     if (!streaming_pad_probe_type(&t->s_streaming_pad, SMT_PACKET))
       continue;
 
-    if (st->es_type == SCT_CA)
+    if (st->es_type == SCT_CA || st->es_type == SCT_CAT)
       continue;
 
     if (st->es_type == SCT_HBBTV) {
@@ -205,7 +205,7 @@ ts_recv_packet0
 
   }
 
-  if (!t->s_scrambled_pass && st->es_type == SCT_CA)
+  if (!t->s_scrambled_pass && (st->es_type == SCT_CA || st->es_type == SCT_CAT))
     return;
 
 skip_cc:
index 45606cdbe96d19279b2d32a640080ac97aafe11d..4551cc14ff1ea46b6f83afe9b937ebfc604487f0 100644 (file)
@@ -2080,12 +2080,12 @@ void service_save ( service_t *t, htsmsg_t *m )
       caid_t *c;
       htsmsg_t *v = htsmsg_create_list();
       LIST_FOREACH(c, &st->es_caids, link) {
-             htsmsg_t *caid = htsmsg_create_map();
+        htsmsg_t *caid = htsmsg_create_map();
 
-             htsmsg_add_u32(caid, "caid", c->caid);
-             if(c->providerid)
-               htsmsg_add_u32(caid, "providerid", c->providerid);
-             htsmsg_add_msg(v, NULL, caid);
+        htsmsg_add_u32(caid, "caid", c->caid);
+        if(c->providerid)
+          htsmsg_add_u32(caid, "providerid", c->providerid);
+        htsmsg_add_msg(v, NULL, caid);
       }
 
       htsmsg_add_msg(sub, "caidlist", v);
@@ -2183,6 +2183,7 @@ add_caid(elementary_stream_t *st, uint16_t caid, uint32_t providerid)
   c->pid = 0;
   c->use = 1;
   c->filter = 0;
+  c->delete_me = 0;
   LIST_INSERT_HEAD(&st->es_caids, c, link);
 }
 
index 708af3930c204816934cffc112336b318a55c84a..fece102666775a83970c11d85455190266853fb3 100644 (file)
@@ -572,6 +572,7 @@ static struct strtab streamtypetab[] = {
   { "HBBTV",      SCT_HBBTV },
   { "THEORA",     SCT_THEORA },
   { "OPUS",       SCT_OPUS },
+  { "CAT",        SCT_CAT },
 };
 
 /**
index d3ee6820d647496a32da332f68407c20b81c7ced..73144562dfb34773e107b5e1c55985b3b949d7eb 100644 (file)
@@ -305,7 +305,8 @@ typedef enum {
   SCT_HBBTV,
   SCT_THEORA,
   SCT_OPUS,
-  SCT_LAST = SCT_OPUS
+  SCT_CAT,     /* MPEG-TS CAT (EMM) data */
+  SCT_LAST = SCT_CAT
 } streaming_component_type_t;
 
 #define SCT_MASK(t) (1 << (t))