]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
pass muxer: add rewrite NIT, fixes #5062
authorJaroslav Kysela <perex@perex.cz>
Fri, 13 Apr 2018 18:11:35 +0000 (20:11 +0200)
committerJaroslav Kysela <perex@perex.cz>
Fri, 13 Apr 2018 18:11:35 +0000 (20:11 +0200)
src/input/mpegts/dvb_psi.c
src/input/mpegts/mpegts_input.c
src/muxer.h
src/muxer/muxer_pass.c
src/profile.c

index 4b5caa4240b3d3710f2d0519115c18d03cd31eaa..0b236946aaacfde1d9877036d7faee4bb38cfbdb 100644 (file)
@@ -2225,8 +2225,8 @@ static void
 psi_tables_dvb ( mpegts_mux_t *mm )
 {
   mpegts_table_add(mm, DVB_NIT_BASE, DVB_NIT_MASK, dvb_nit_callback,
-                   NULL, "nit", LS_TBL_BASE, MT_QUICKREQ | MT_CRC, DVB_NIT_PID,
-                   MPS_WEIGHT_NIT);
+                   NULL, "nit", LS_TBL_BASE, MT_QUICKREQ | MT_CRC | MT_RECORD,
+                   DVB_NIT_PID, MPS_WEIGHT_NIT);
   mpegts_table_add(mm, DVB_SDT_BASE, DVB_SDT_MASK, dvb_sdt_callback,
                    NULL, "sdt", LS_TBL_BASE, MT_QUICKREQ | MT_CRC | MT_RECORD,
                    DVB_SDT_PID, MPS_WEIGHT_SDT);
index b7bdf1d531993e89142494004455edc5f87c5575..7c6a3a554205a58eae98bf3ea4ce416fbe338418 100644 (file)
@@ -1072,7 +1072,7 @@ static void mpegts_input_analyze_table_queue ( mpegts_input_t *mi )
   memset(&counters, 0, sizeof(counters));
   TAILQ_FOREACH(mtf, &mi->mi_table_queue, mtf_link) {
     const uint8_t *tsb = mtf->mtf_tsb;
-    pid = (tsb[1] << 8) | tsb[2];
+    pid = ((tsb[1] << 8) & 0x0f) | tsb[2];
     sizes[pid] += mtf->mtf_len;
     counters[pid]++;
   }
index 9b3ba408ced7f5cef4fdb87eb95d1540e5679e94..9801f9b78f6b7e902e92402d6d6a8f8fe2e1e9cd 100644 (file)
@@ -72,6 +72,7 @@ typedef struct muxer_config {
       int              m_rewrite_pat;
       int              m_rewrite_pmt;
       int              m_rewrite_sdt;
+      int              m_rewrite_nit;
       int              m_rewrite_eit;
       char            *m_cmdline;
       char            *m_mime;
index a6ea51dd16e94f403c0aebe268d2b4a4722f8b35..b3c96b211b7578001da8e097a063af565cb93a1a 100644 (file)
@@ -49,6 +49,7 @@ typedef struct pass_muxer {
 
   /* TS muxing */
   uint8_t  pm_rewrite_sdt;
+  uint8_t  pm_rewrite_nit;
   uint8_t  pm_rewrite_eit;
 
   uint16_t pm_pmt_pid;
@@ -58,6 +59,7 @@ typedef struct pass_muxer {
   mpegts_psi_table_t pm_pat;
   mpegts_psi_table_t pm_pmt;
   mpegts_psi_table_t pm_sdt;
+  mpegts_psi_table_t pm_nit;
   mpegts_psi_table_t pm_eit;
 
 } pass_muxer_t;
@@ -199,6 +201,8 @@ pass_muxer_sdt_cb(mpegts_psi_table_t *mt, const uint8_t *buf, int len)
   while (len >= 5) {
     sid = (buf[0] << 8) | buf[1];
     l = (buf[3] & 0x0f) << 8 | buf[4];
+    if (l > len - 5)
+      return;
     if (sid != pm->pm_src_sid) {
       buf += l + 5;
       len -= l + 5;
@@ -229,6 +233,45 @@ pass_muxer_sdt_cb(mpegts_psi_table_t *mt, const uint8_t *buf, int len)
   }
 }
 
+/*
+ *
+ */
+static void
+pass_muxer_nit_cb(mpegts_psi_table_t *mt, const uint8_t *buf, int len)
+{
+  pass_muxer_t *pm;
+  uint8_t out[4096], *ob;
+  int l, ol;
+
+  /* filter out the other networks */
+  if (buf[0] != 0x40)
+    return;
+
+  if (len < 10)
+    return;
+
+  pm = (pass_muxer_t*)mt->mt_opaque;
+   l = (buf[8] & 0x0f) << 8 | buf[9];
+  ol = 2 + 3 + 2 + 3 + l;
+
+  if (ol > len)
+    return;
+
+  if (sizeof(out) < ol) {
+    tvherror(LS_PASS, "NIT entry too long (%i)", ol);
+    return;
+  }
+
+  memcpy(out, buf, ol);
+
+  ol = dvb_table_append_crc32(out, ol, sizeof(out));
+
+  if (ol > 0 && (l = dvb_table_remux(mt, out, ol, &ob)) > 0) {
+    pass_muxer_write((muxer_t *)pm, ob, l);
+    free(ob);
+  }
+}
+
 /*
  *
  */
@@ -328,6 +371,7 @@ pass_muxer_reconfigure(muxer_t* m, const struct streaming_start *ss)
     pm->pm_dst_sid   = ss->ss_service_id;
   pm->pm_pmt_pid     = ss->ss_pmt_pid;
   pm->pm_rewrite_sdt = !!pm->m_config.u.pass.m_rewrite_sdt;
+  pm->pm_rewrite_nit = !!pm->m_config.u.pass.m_rewrite_nit;
   pm->pm_rewrite_eit = !!pm->m_config.u.pass.m_rewrite_eit;
 
   for(i=0; i < ss->ss_num_components; i++) {
@@ -338,6 +382,10 @@ pass_muxer_reconfigure(muxer_t* m, const struct streaming_start *ss)
       tvhwarn(LS_PASS, "SDT PID shared with A/V, rewrite disabled");
       pm->pm_rewrite_sdt = 0;
     }
+    if (ssc->es_pid == DVB_NIT_PID && pm->pm_rewrite_nit) {
+      tvhwarn(LS_PASS, "NIT PID shared with A/V, rewrite disabled");
+      pm->pm_rewrite_nit = 0;
+    }
     if (ssc->es_pid == DVB_EIT_PID && pm->pm_rewrite_eit) {
       tvhwarn(LS_PASS, "EIT PID shared with A/V, rewrite disabled");
       pm->pm_rewrite_eit = 0;
@@ -496,7 +544,7 @@ pass_muxer_write_ts(muxer_t *m, pktbuf_t *pb)
   
   /* Rewrite PAT/PMT in operation */
   if (pm->m_config.u.pass.m_rewrite_pat || pm->m_config.u.pass.m_rewrite_pmt ||
-      pm->pm_rewrite_sdt || pm->pm_rewrite_eit) {
+      pm->pm_rewrite_sdt || pm->pm_rewrite_nit || pm->pm_rewrite_eit) {
 
     for (tsb = pktbuf_ptr(pb), len2 = pktbuf_len(pb), len = 0;
          len2 > 0; tsb += l, len2 -= l) {
@@ -508,6 +556,7 @@ pass_muxer_write_ts(muxer_t *m, pktbuf_t *pb)
       if ( (pm->m_config.u.pass.m_rewrite_pat && pid == DVB_PAT_PID) ||
            (pm->m_config.u.pass.m_rewrite_pmt && pid == pm->pm_pmt_pid) ||
            (pm->pm_rewrite_sdt && pid == DVB_SDT_PID) ||
+           (pm->pm_rewrite_nit && pid == DVB_NIT_PID) ||
            (pm->pm_rewrite_eit && pid == DVB_EIT_PID) ) {
 
         /* Flush */
@@ -528,6 +577,11 @@ pass_muxer_write_ts(muxer_t *m, pktbuf_t *pb)
         
           dvb_table_parse(&pm->pm_sdt, "-", tsb, l, 1, 0, pass_muxer_sdt_cb);
 
+        /* NIT */
+        } else if (pid == DVB_NIT_PID) {
+        
+          dvb_table_parse(&pm->pm_nit, "-", tsb, l, 1, 0, pass_muxer_nit_cb);
+
         /* EIT */
         } else if (pid == DVB_EIT_PID) {
         
@@ -628,6 +682,7 @@ pass_muxer_destroy(muxer_t *m)
   dvb_table_parse_done(&pm->pm_pat);
   dvb_table_parse_done(&pm->pm_pmt);
   dvb_table_parse_done(&pm->pm_sdt);
+  dvb_table_parse_done(&pm->pm_nit);
   dvb_table_parse_done(&pm->pm_eit);
 
   muxer_config_free(&pm->m_config);
@@ -668,6 +723,8 @@ pass_muxer_create(const muxer_config_t *m_cfg,
                        DVB_PMT_BASE, DVB_PMT_MASK, pm);
   dvb_table_parse_init(&pm->pm_sdt, "pass-sdt", LS_TBL_PASS, DVB_SDT_PID,
                        DVB_SDT_BASE, DVB_SDT_MASK, pm);
+  dvb_table_parse_init(&pm->pm_nit, "pass-nit", LS_TBL_PASS, DVB_NIT_PID,
+                       DVB_NIT_BASE, DVB_NIT_MASK, pm);
   dvb_table_parse_init(&pm->pm_eit, "pass-eit", LS_TBL_PASS, DVB_EIT_PID,
                        0, 0, pm);
 
index 07e25eaf49d78cd383d987620795568b8d86aaf2..7c693789ee5013d18e772e27bd4d1ca57b91b3e8 100644 (file)
@@ -1254,6 +1254,7 @@ typedef struct profile_mpegts {
   int pro_rewrite_pmt;
   int pro_rewrite_pat;
   int pro_rewrite_sdt;
+  int pro_rewrite_nit;
   int pro_rewrite_eit;
 } profile_mpegts_t;
 
@@ -1267,6 +1268,7 @@ profile_pass_rewrite_sid_set (void *in, const void *v)
       pro->pro_rewrite_pmt =
       pro->pro_rewrite_pat =
       pro->pro_rewrite_sdt =
+      pro->pro_rewrite_nit =
       pro->pro_rewrite_eit = 1;
     }
     pro->pro_rewrite_sid = *val;
@@ -1306,6 +1308,12 @@ profile_pass_rewrite_sdt_set (void *in, const void *v)
   return profile_pass_int_set(in, v, &((profile_mpegts_t *)in)->pro_rewrite_sdt);
 }
 
+static int
+profile_pass_rewrite_nit_set (void *in, const void *v)
+{
+  return profile_pass_int_set(in, v, &((profile_mpegts_t *)in)->pro_rewrite_nit);
+}
+
 static int
 profile_pass_rewrite_eit_set (void *in, const void *v)
 {
@@ -1380,6 +1388,19 @@ const idclass_t profile_mpegts_pass_class =
       .def.i    = 1,
       .group    = 2
     },
+    {
+      .type     = PT_BOOL,
+      .id       = "rewrite_nit",
+      .name     = N_("Rewrite NIT"),
+      .desc     = N_("Rewrite NIT (Network Information Table) packets "
+                     "to only include information about the currently-"
+                     "streamed service."),
+      .off      = offsetof(profile_mpegts_t, pro_rewrite_nit),
+      .set      = profile_pass_rewrite_nit_set,
+      .opts     = PO_EXPERT,
+      .def.i    = 1,
+      .group    = 2
+    },
     {
       .type     = PT_BOOL,
       .id       = "rewrite_eit",
@@ -1415,6 +1436,7 @@ profile_mpegts_pass_reopen(profile_chain_t *prch,
   c.u.pass.m_rewrite_pat = pro->pro_rewrite_pat;
   c.u.pass.m_rewrite_pmt = pro->pro_rewrite_pmt;
   c.u.pass.m_rewrite_sdt = pro->pro_rewrite_sdt;
+  c.u.pass.m_rewrite_nit = pro->pro_rewrite_nit;
   c.u.pass.m_rewrite_eit = pro->pro_rewrite_eit;
 
   assert(!prch->prch_muxer);
@@ -1449,6 +1471,7 @@ profile_mpegts_pass_builder(void)
   pro->pro_rewrite_pat = 1;
   pro->pro_rewrite_pmt = 1;
   pro->pro_rewrite_sdt = 1;
+  pro->pro_rewrite_nit = 1;
   pro->pro_rewrite_eit = 1;
   return (profile_t *)pro;
 }
@@ -1544,6 +1567,7 @@ profile_mpegts_spawn_reopen(profile_chain_t *prch,
   c.u.pass.m_rewrite_pat = 1;
   c.u.pass.m_rewrite_pmt = 1;
   c.u.pass.m_rewrite_sdt = 1;
+  c.u.pass.m_rewrite_nit = 1;
   c.u.pass.m_rewrite_eit = 1;
   mystrset(&c.u.pass.m_cmdline, pro->pro_cmdline);
   mystrset(&c.u.pass.m_mime, pro->pro_mime);