]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
dvb_psi: nit,sdt,vct callbacks - operate on all muxes with same tsid, fixes #2605
authorJaroslav Kysela <perex@perex.cz>
Sun, 11 Jan 2015 20:43:22 +0000 (21:43 +0100)
committerJaroslav Kysela <perex@perex.cz>
Sun, 11 Jan 2015 20:43:22 +0000 (21:43 +0100)
src/input/mpegts/dvb_psi.c

index 78579c576a8b9a2557e4020236526dde8b67117f..fd40737caffcdb28fc7d198c6af62fb562e7e569 100644 (file)
@@ -1274,6 +1274,130 @@ complete:
   }
 }
 
+static int
+dvb_nit_mux
+  (mpegts_table_t *mt, mpegts_mux_t *mux, mpegts_mux_t *mm,
+   mpegts_network_t *mn, uint16_t onid, uint16_t tsid,
+   const uint8_t *lptr, int llen, uint8_t tableid, dvb_bat_id_t *bi)
+{
+  uint32_t priv = 0;
+  uint8_t dtag;
+  int dllen, dlen;
+  const uint8_t *dlptr, *dptr, *lptr_orig = lptr;
+  const char *charset;
+  char buf[128], dauth[256];
+
+  if (mux && !mux->mm_enabled)
+    bi = NULL;
+
+  charset = dvb_charset_find(mn, mux, NULL);
+
+  if (mux)
+    mpegts_mux_nice_name(mux, buf, sizeof(buf));
+  else
+    strcpy(buf, "<none>");
+  tvhdebug(mt->mt_name, "  onid %04X (%d) tsid %04X (%d) mux %s", onid, onid, tsid, tsid, buf);
+
+  DVB_DESC_FOREACH(lptr, llen, 4, dlptr, dllen, dtag, dlen, dptr) {
+    tvhtrace(mt->mt_name, "    dtag %02X dlen %d", dtag, dlen);
+
+    /* User-defined */
+    if (mt->mt_mux_cb && mux) {
+      int i = 0;
+      while (mt->mt_mux_cb[i].cb) {
+        if (mt->mt_mux_cb[i].tag == dtag)
+          break;
+        i++;
+        }
+      if (mt->mt_mux_cb[i].cb) {
+        if (mt->mt_mux_cb[i].cb(mt, mux, dtag, dptr, dlen))
+          return -1;
+        dtag = 0;
+      }
+    }
+
+    /* Pre-defined */
+    switch (dtag) {
+    default:
+    case 0:
+      break;
+
+    /* nit only */
+#if ENABLE_MPEGTS_DVB
+    case DVB_DESC_SAT_DEL:
+    case DVB_DESC_CABLE_DEL:
+    case DVB_DESC_TERR_DEL:
+      if (dtag == DVB_DESC_SAT_DEL)
+        mux = dvb_desc_sat_del(mm, onid, tsid, dptr, dlen);
+      else if (dtag == DVB_DESC_CABLE_DEL)
+        mux = dvb_desc_cable_del(mm, onid, tsid, dptr, dlen);
+      else
+        mux = dvb_desc_terr_del(mm, onid, tsid, dptr, dlen);
+      if (mux) {
+        mpegts_mux_set_onid(mux, onid);
+        mpegts_mux_set_tsid(mux, tsid, 0);
+      }
+      break;
+#endif
+
+    /* Both */
+    case DVB_DESC_DEF_AUTHORITY:
+      if (dvb_get_string(dauth, sizeof(dauth), dptr, dlen, charset, NULL))
+        return -1;
+      tvhdebug(mt->mt_name, "    default auth [%s]", dauth);
+      if (mux && *dauth)
+        mpegts_mux_set_crid_authority(mux, dauth);
+      break;
+    case DVB_DESC_SERVICE_LIST:
+      if (dvb_desc_service_list(mt->mt_name, dptr, dlen, mux, bi))
+        return -1;
+      break;
+    case DVB_DESC_PRIVATE_DATA:
+#if ENABLE_MPEGTS_DVB
+      if (dlen == 4) {
+        priv = (dptr[0] << 24) | (dptr[1] << 16) | (dptr[2] << 8) | dptr[3];
+        tvhtrace(mt->mt_name, "      private %08X", priv);
+      }
+#endif
+      break;
+    case 0x81:
+      if (priv == 0) goto lcn;
+    case 0x82:
+      if (priv == 0) goto lcn;
+    case 0x83:
+      if (priv == 0 || priv == 0x28 || priv == 0x29 || priv == 0xa5 ||
+          priv == 0x233A) goto lcn;
+    case 0x86:
+      if (priv == 0) goto lcn;
+    case 0x93:
+      if (priv == 0 || priv == 0x362275)
+      /* fall thru */
+lcn:
+      if (dvb_desc_local_channel(mt->mt_name, dptr, dlen, dtag, mux, bi))
+        return -1;
+      break;
+    case DVB_DESC_FREESAT_LCN:
+#if ENABLE_MPEGTS_DVB
+      if (bi && tableid == 0x4A && priv == PRIV_FSAT) {
+        dvb_freesat_local_channels(bi, mt->mt_name, dptr, dlen);
+        bi->freesat = 1;
+      }
+#endif
+      break;
+    case DVB_DESC_BSKYB_LCN:
+#if ENABLE_MPEGTS_DVB
+      if (bi && tableid == 0x4A && priv == 2) {
+        dvb_bskyb_local_channels(bi, mt->mt_name, dptr, dlen, mux);
+        bi->bskyb = 1;
+      }
+#endif
+      break;
+    }
+  }
+
+  return lptr - lptr_orig;
+}
+
 int
 dvb_nit_callback
   (mpegts_table_t *mt, const uint8_t *ptr, int len, int tableid)
@@ -1282,17 +1406,17 @@ dvb_nit_callback
   int r, sect, last, ver;
   uint32_t priv = 0;
   uint8_t  dtag;
-  int llen, dllen, dlen;
-  const uint8_t *lptr, *dlptr, *dptr;
+  int llen, dlen;
+  const uint8_t *lptr, *dptr;
   uint16_t nbid = 0, onid, tsid;
   mpegts_mux_t     *mm = mt->mt_mux, *mux;
   mpegts_network_t *mn = mm->mm_network;
-  char name[256], dauth[256];
+  char name[256];
   mpegts_table_state_t  *st  = NULL;
+  const char *charset;
   bouquet_t *bq = NULL;
   dvb_bat_t *b = NULL;
   dvb_bat_id_t *bi = NULL;
-  const char *charset;
 
   /* Net/Bat ID */
   nbid = (ptr[0] << 8) | ptr[1];
@@ -1414,116 +1538,27 @@ dvb_nit_callback
   }
 
   /* Transport length */
-  priv = 0;
   DVB_LOOP_FOREACH(ptr, len, 0, lptr, llen, 6) {
     tsid  = (lptr[0] << 8) | lptr[1];
     onid  = (lptr[2] << 8) | lptr[3];
 
     /* Find existing mux */
+    r = -1;
     LIST_FOREACH(mux, &mn->mn_muxes, mm_network_link)
-      if (mux->mm_onid == onid && mux->mm_tsid == tsid)
-        break;
-    charset = dvb_charset_find(mn, mux, NULL);
-
-
-    tvhdebug(mt->mt_name, "  onid %04X (%d) tsid %04X (%d) mux %p", onid, onid, tsid, tsid, mux);
-
-    DVB_DESC_FOREACH(lptr, llen, 4, dlptr, dllen, dtag, dlen, dptr) {
-      tvhtrace(mt->mt_name, "    dtag %02X dlen %d", dtag, dlen);
-
-      /* User-defined */
-      if (mt->mt_mux_cb && mux) {
-        int i = 0;
-        while (mt->mt_mux_cb[i].cb) {
-          if (mt->mt_mux_cb[i].tag == dtag)
-            break;
-          i++;
-        }
-        if (mt->mt_mux_cb[i].cb) {
-          if (mt->mt_mux_cb[i].cb(mt, mux, dtag, dptr, dlen))
-            return -1;
-          dtag = 0;
-        }
-      }
-
-      /* Pre-defined */
-      switch (dtag) {
-        default:
-        case 0:
-          break;
-    
-        /* nit only */
-#if ENABLE_MPEGTS_DVB
-        case DVB_DESC_SAT_DEL:
-        case DVB_DESC_CABLE_DEL:
-        case DVB_DESC_TERR_DEL:
-          if (dtag == DVB_DESC_SAT_DEL)
-            mux = dvb_desc_sat_del(mm, onid, tsid, dptr, dlen);
-          else if (dtag == DVB_DESC_CABLE_DEL)
-            mux = dvb_desc_cable_del(mm, onid, tsid, dptr, dlen);
-          else
-            mux = dvb_desc_terr_del(mm, onid, tsid, dptr, dlen);
-          if (mux) {
-            mpegts_mux_set_onid(mux, onid);
-            mpegts_mux_set_tsid(mux, tsid, 0);
-          }
-          break;
-#endif
-        
-        /* Both */
-        case DVB_DESC_DEF_AUTHORITY:
-          if (dvb_get_string(dauth, sizeof(dauth), dptr, dlen, charset, NULL))
-            return -1;
-          tvhdebug(mt->mt_name, "    default auth [%s]", dauth);
-          if (mux && *dauth)
-            mpegts_mux_set_crid_authority(mux, dauth);
-          break;
-        case DVB_DESC_SERVICE_LIST:
-          if (dvb_desc_service_list(mt->mt_name, dptr, dlen, mux, bi))
-            return -1;
-          break;
-        case DVB_DESC_PRIVATE_DATA:
-#if ENABLE_MPEGTS_DVB
-          if (dlen == 4) {
-            priv = (dptr[0] << 24) | (dptr[1] << 16) | (dptr[2] << 8) | dptr[3];
-            tvhtrace(mt->mt_name, "      private %08X", priv);
-          }
-#endif
-          break;
-        case 0x81:
-          if (priv == 0) goto lcn;
-        case 0x82:
-          if (priv == 0) goto lcn;
-        case 0x83:
-          if (priv == 0 || priv == 0x28 || priv == 0x29 || priv == 0xa5 ||
-              priv == 0x233A) goto lcn;
-        case 0x86:
-          if (priv == 0) goto lcn;
-        case 0x93:
-          if (priv == 0 || priv == 0x362275)
-          /* fall thru */
-lcn:
-          if (dvb_desc_local_channel(mt->mt_name, dptr, dlen, dtag, mux, bi))
-            return -1;
-          break;
-        case DVB_DESC_FREESAT_LCN:
-#if ENABLE_MPEGTS_DVB
-          if (bi && tableid == 0x4A && priv == PRIV_FSAT) {
-            dvb_freesat_local_channels(bi, mt->mt_name, dptr, dlen);
-            bi->freesat = 1;
-          }
-#endif
-          break;
-        case DVB_DESC_BSKYB_LCN:
-#if ENABLE_MPEGTS_DVB
-          if (bi && tableid == 0x4A && priv == 2) {
-            dvb_bskyb_local_channels(bi, mt->mt_name, dptr, dlen, mux);
-            bi->bskyb = 1;
-          }
-#endif
-          break;
+      if (mux->mm_onid == onid && mux->mm_tsid == tsid) {
+        r = dvb_nit_mux(mt, mux, mm, mn, onid, tsid, lptr, llen, tableid, bi);
+        if (r < 0)
+          return r;
       }
+      
+    /* New mux */
+    if (r == -1) {
+      r = dvb_nit_mux(mt, NULL, mm, mn, onid, tsid, lptr, llen, tableid, bi);
+      if (r < 0)
+        return r;
     }
+    lptr += r;
+    llen -= r;
   }
 
   /* End */
@@ -1533,45 +1568,23 @@ lcn:
 /**
  * DVB SDT (Service Description Table)
  */
-int
-dvb_sdt_callback
-  (mpegts_table_t *mt, const uint8_t *ptr, int len, int tableid)
+static int
+dvb_sdt_mux
+  (mpegts_table_t *mt, mpegts_mux_t *mm, mpegts_mux_t *mm_orig,
+   const uint8_t *ptr, int len, uint8_t tableid)
 {
-  int r, sect, last, ver, extraid, p02 = 0;
-  uint16_t onid, tsid;
+  uint32_t priv = 0;
   uint8_t dtag;
-  int llen, dlen;
   const uint8_t *lptr, *dptr;
-  mpegts_mux_t     *mm = mt->mt_mux, *mm_orig = mm;
+  int llen, dlen;
   mpegts_network_t *mn = mm->mm_network;
-  mpegts_table_state_t  *st  = NULL;
-
-  /* Begin */
-  tsid    = ptr[0] << 8 | ptr[1];
-  onid    = ptr[5] << 8 | ptr[6];
-  extraid = ((int)onid) << 16 | tsid;
-  if (tableid != 0x42 && tableid != 0x46) return -1;
-  r = dvb_table_begin(mt, ptr, len, tableid, extraid, 8, &st, &sect, &last, &ver);
-  if (r != 1) return r;
+  char buf[128];
 
-  /* ID */
-  tvhdebug("sdt", "onid %04X (%d) tsid %04X (%d)", onid, onid, tsid, tsid);
+  mpegts_mux_nice_name(mm, buf, sizeof(buf));
 
-  /* Find Transport Stream */
-  if (tableid == 0x42) {
-    mpegts_mux_set_onid(mm, onid);
-    mpegts_mux_set_tsid(mm, tsid, 1);
-  } else {
-    LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link)
-      if (mm->mm_onid == onid && mm->mm_tsid == tsid)
-        break;
-    if (!mm)
-      goto done;
-  }
+  tvhdebug("sdt", "mux %s", buf);
 
   /* Service loop */
-  len -= 8;
-  ptr += 8;
   while(len >= 5) {
     mpegts_service_t *s;
     int master = 0, save = 0, save2 = 0;
@@ -1614,11 +1627,15 @@ dvb_sdt_callback
             return -1;
           break;
         case DVB_DESC_PRIVATE_DATA:
-          if (!memcmp(dptr, "\x00\x00\x00\x02", 4))
-            p02 = 1;
+#if ENABLE_MPEGTS_DVB
+          if (dlen == 4) {
+            priv = (dptr[0] << 24) | (dptr[1] << 16) | (dptr[2] << 8) | dptr[3];
+            tvhtrace(mt->mt_name, "  private %08X", priv);
+          }
+#endif
           break;
         case DVB_DESC_BSKYB_NVOD:
-          if (p02)
+          if (priv == 2)
             if (dvb_get_string(sname, sizeof(sname), dptr, dlen, charset, NULL))
               return -1;
           break;
@@ -1689,8 +1706,51 @@ dvb_sdt_callback
     }
   }
 
+  return 0;
+}
+
+int
+dvb_sdt_callback
+  (mpegts_table_t *mt, const uint8_t *ptr, int len, int tableid)
+{
+  int r, sect, last, ver, extraid;
+  uint16_t onid, tsid;
+  mpegts_mux_t     *mm = mt->mt_mux, *mm_orig = mm;
+  mpegts_network_t *mn = mm->mm_network;
+  mpegts_table_state_t  *st  = NULL;
+
+  /* Begin */
+  tsid    = ptr[0] << 8 | ptr[1];
+  onid    = ptr[5] << 8 | ptr[6];
+  extraid = ((int)onid) << 16 | tsid;
+  if (tableid != 0x42 && tableid != 0x46) return -1;
+  r = dvb_table_begin(mt, ptr, len, tableid, extraid, 8, &st, &sect, &last, &ver);
+  if (r != 1) return r;
+
+  /* ID */
+  tvhdebug("sdt", "onid %04X (%d) tsid %04X (%d)", onid, onid, tsid, tsid);
+
+  /* Service descriptors */
+  len -= 8;
+  ptr += 8;
+
+  /* Find Transport Stream */
+  if (tableid == 0x42) {
+    mpegts_mux_set_onid(mm, onid);
+    mpegts_mux_set_tsid(mm, tsid, 1);
+    r = dvb_sdt_mux(mt, mm, mm, ptr, len, tableid);
+    if (r)
+      return r;
+  } else {
+    LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link)
+      if (mm->mm_onid == onid && mm->mm_tsid == tsid) {
+        r = dvb_sdt_mux(mt, mm, mm_orig, ptr, len, tableid);
+        if (r)
+          return r;
+      }
+  }
+
   /* Done */
-done:
   return dvb_table_end(mt, st, sect);
 }
 
@@ -1752,28 +1812,25 @@ atsc_vct_callback
 
     /* Find mux */
     LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link)
-      if (mm->mm_tsid == tsid)
-        break;
-    if (!mm) goto next;
-
-    /* Find the service */
-    if (!(s = mpegts_service_find(mm, sid, 0, 1, &save)))
-      goto next;
-
-    /* Update */
-    if (strcmp(s->s_dvb_svcname ?: "", chname)) {
-      tvh_str_set(&s->s_dvb_svcname, chname);
-      save = 1;
-    }
-    if (s->s_dvb_channel_num != maj || s->s_dvb_channel_minor != min) {
-      s->s_dvb_channel_num = maj;
-      s->s_dvb_channel_minor = min;
-      save = 1;
-    }
+      if (mm->mm_tsid == tsid) {
+        /* Find the service */
+        if (!(s = mpegts_service_find(mm, sid, 0, 1, &save)))
+          continue;
 
-    /* Save */
-    if (save)
-      s->s_config_save((service_t*)s);
+        /* Update */
+        if (strcmp(s->s_dvb_svcname ?: "", chname)) {
+          tvh_str_set(&s->s_dvb_svcname, chname);
+          save = 1;
+        }
+        if (s->s_dvb_channel_num != maj || s->s_dvb_channel_minor != min) {
+          s->s_dvb_channel_num = maj;
+          s->s_dvb_channel_minor = min;
+          save = 1;
+        }
+        /* Save */
+        if (save)
+          s->s_config_save((service_t*)s);
+     }
 
     /* Move on */
 next: