]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
DVB-S2/T2 multistream support.
authorCrazyCat <crazycat69@narod.ru>
Sun, 25 Jan 2015 22:30:29 +0000 (00:30 +0200)
committerJaroslav Kysela <perex@perex.cz>
Mon, 2 Feb 2015 13:53:37 +0000 (14:53 +0100)
src/input/mpegts/dvb.h
src/input/mpegts/dvb_support.c
src/input/mpegts/linuxdvb/linuxdvb_frontend.c
src/input/mpegts/mpegts_mux_dvb.c
src/input/mpegts/mpegts_network_dvb.c
src/input/mpegts/scanfile.c

index 2b5f4a80f7c27d299a3a5164915ad09bd16e4b69..bdd5509eb5b885e8803ddd1b76bba81d3d2c0598 100644 (file)
@@ -410,6 +410,12 @@ typedef enum dvb_fe_rolloff {
   DVB_ROLLOFF_35         = 350,
 } dvb_fe_rolloff_t;
 
+typedef enum dvb_fe_pls_mode {
+  DVB_PLS_ROOT = 0,
+  DVB_PLS_GOLD,
+  DVB_PLS_COMBO,
+} dvb_fe_pls_mode_t;
+
 typedef enum dvb_polarisation {
   DVB_POLARISATION_HORIZONTAL     = 0x00,
   DVB_POLARISATION_VERTICAL       = 0x01,
@@ -449,6 +455,9 @@ typedef struct dvb_mux_conf
   dvb_fe_spectral_inversion_t dmc_fe_inversion;
   dvb_fe_rolloff_t            dmc_fe_rolloff;
   dvb_fe_pilot_t              dmc_fe_pilot;
+  int32_t                     dmc_fe_stream_id;
+  dvb_fe_pls_mode_t           dmc_fe_pls_mode;
+  uint32_t                    dmc_fe_pls_code;
   union {
     dvb_qpsk_config_t         dmc_fe_qpsk;
     dvb_qam_config_t          dmc_fe_qam;
@@ -473,6 +482,7 @@ const char *dvb_hier2str    ( int hier );
 const char *dvb_pol2str     ( int pol );
 const char *dvb_type2str    ( int type );
 const char *dvb_pilot2str   ( int pilot );
+const char *dvb_plsmode2str   ( int pls_mode );
 #define dvb_feclo2str dvb_fec2str
 #define dvb_fechi2str dvb_fec2str
 
@@ -488,6 +498,7 @@ int dvb_str2hier    ( const char *str );
 int dvb_str2pol     ( const char *str );
 int dvb_str2type    ( const char *str );
 int dvb_str2pilot   ( const char *str );
+int dvb_str2plsmode ( const char *str );
 #define dvb_str2feclo dvb_str2fec
 #define dvb_str2fechi dvb_str2fec
 
index 3a6ad44351dcf3b4a3fef5e6b71d86b312b8fad6..912a90252fb3d54332c6303313fb3cf65a93d8ce 100644 (file)
@@ -758,14 +758,23 @@ const static struct strtab pilottab[] = {
   {"OFF",  DVB_PILOT_OFF}
 };
 dvb_str2val(pilot);
+
+const static struct strtab plsmodetab[] = {
+  {"ROOT", DVB_PLS_ROOT},
+  {"GOLD", DVB_PLS_GOLD},
+  {"COMBO", DVB_PLS_COMBO},
+};
+dvb_str2val(plsmode);
 #undef dvb_str2val
 
+
+
 static int
 dvb_mux_conf_str_dvbt ( dvb_mux_conf_t *dmc, char *buf, size_t bufsize )
 {
   return
   snprintf(buf, bufsize,
-           "%s freq %d bw %s cons %s hier %s code_rate %s:%s guard %s trans %s",
+           "%s freq %d bw %s cons %s hier %s code_rate %s:%s guard %s trans %s plp_id %d",
            dvb_delsys2str(dmc->dmc_fe_delsys),
            dmc->dmc_fe_freq,
            dvb_bw2str(dmc->u.dmc_fe_ofdm.bandwidth),
@@ -774,7 +783,8 @@ dvb_mux_conf_str_dvbt ( dvb_mux_conf_t *dmc, char *buf, size_t bufsize )
            dvb_fec2str(dmc->u.dmc_fe_ofdm.code_rate_HP),
            dvb_fec2str(dmc->u.dmc_fe_ofdm.code_rate_LP),
            dvb_guard2str(dmc->u.dmc_fe_ofdm.guard_interval),
-           dvb_mode2str(dmc->u.dmc_fe_ofdm.transmission_mode));
+           dvb_mode2str(dmc->u.dmc_fe_ofdm.transmission_mode),
+           dmc->dmc_fe_stream_id);
 }
 
 static int
@@ -797,7 +807,7 @@ dvb_mux_conf_str_dvbs ( dvb_mux_conf_t *dmc, char *buf, size_t bufsize )
   const char dir = dmc->u.dmc_fe_qpsk.orbital_dir;
   return
   snprintf(buf, bufsize,
-           "%s pos %d.%d%c freq %d %c sym %d fec %s mod %s roff %s",
+           "%s pos %d.%d%c freq %d %c sym %d fec %s mod %s roff %s is_id %d pls_mode %s pls_code %d",
            dvb_delsys2str(dmc->dmc_fe_delsys),
            dmc->u.dmc_fe_qpsk.orbital_pos / 10,
            dmc->u.dmc_fe_qpsk.orbital_pos % 10,
@@ -807,7 +817,10 @@ dvb_mux_conf_str_dvbs ( dvb_mux_conf_t *dmc, char *buf, size_t bufsize )
            dmc->u.dmc_fe_qpsk.symbol_rate,
            dvb_fec2str(dmc->u.dmc_fe_qpsk.fec_inner),
            dvb_qam2str(dmc->dmc_fe_modulation),
-           dvb_rolloff2str(dmc->dmc_fe_rolloff));
+           dvb_rolloff2str(dmc->dmc_fe_rolloff),
+           dmc->dmc_fe_stream_id,
+           dvb_plsmode2str(dmc->dmc_fe_pls_mode),
+           dmc->dmc_fe_pls_code);
 }
 
 static int
index 84a83ec09436882fd6b5dbc000970c5f9e1ecec8..f56bad69f9e7dee22e0dc924ec5cd1957ddbef1d 100644 (file)
@@ -1297,6 +1297,13 @@ linuxdvb_frontend_tune0
     S2CMD(DTV_GUARD_INTERVAL,    p.u.ofdm.guard_interval);
     S2CMD(DTV_HIERARCHY,         p.u.ofdm.hierarchy_information);
 #endif
+    if (lm->lm_tuning.dmc_fe_delsys == DVB_SYS_DVBT2) {
+#if DVB_VER_ATLEAST(5,9)
+      S2CMD(DTV_STREAM_ID, dmc->dmc_fe_stream_id);
+#elif DVB_VER_ATLEAST(5,3)
+      S2CMD(DTV_DVBT2_PLP_ID, dmc->dmc_fe_stream_id);
+#endif
+    }
 
   /* DVB-C */
   } else if (lfe->lfe_type == DVB_TYPE_C) {
@@ -1308,12 +1315,19 @@ linuxdvb_frontend_tune0
   } else if (lfe->lfe_type == DVB_TYPE_S) {
     S2CMD(DTV_SYMBOL_RATE,       p.u.qpsk.symbol_rate);
     S2CMD(DTV_INNER_FEC,         p.u.qpsk.fec_inner);
-    S2CMD(DTV_PILOT,             TR(pilot, pilot_tbl, PILOT_AUTO));
     S2CMD(DTV_MODULATION,        TR(modulation, mod_tbl, QPSK));
     if (lm->lm_tuning.dmc_fe_delsys == DVB_SYS_DVBS) {
       S2CMD(DTV_ROLLOFF,         ROLLOFF_35);
     } else {
+      S2CMD(DTV_PILOT,           TR(pilot, pilot_tbl, PILOT_AUTO));
       S2CMD(DTV_ROLLOFF,         TR(rolloff, rolloff_tbl, ROLLOFF_AUTO));
+      r = dmc->dmc_fe_stream_id != -1 ? (dmc->dmc_fe_stream_id & 0xFF) |
+          ((dmc->dmc_fe_pls_code & 0x3FFFF)<<8) | ((dmc->dmc_fe_pls_mode & 0x3)<<26) : r;
+#if DVB_VER_ATLEAST(5,9)
+      S2CMD(DTV_STREAM_ID, r );
+#elif DVB_VER_ATLEAST(5,3)
+      S2CMD(DTV_DVBT2_PLP_ID, r);
+#endif
     }
 
   /* ATSC */
index 7d81f6e91f219be08c53bbf261db4bc07d1bfa95..9decd58b21c4681f0f7179125e40b60dd4d7e9b7 100644 (file)
@@ -218,6 +218,13 @@ const idclass_t dvb_mux_dvbt_class =
     {
       MUX_PROP_STR("fec_lo", "FEC Low", dvbt, feclo, "AUTO"),
     },
+    {
+      .type     = PT_INT,
+      .id       = "plp_id",
+      .name     = "PLP ID",
+      .off      = offsetof(dvb_mux_t, lm_tuning.dmc_fe_stream_id),
+      .def.i   = 0,
+    },
     {}
   }
 };
@@ -401,6 +408,33 @@ dvb_mux_dvbs_class_pilot_list ( void *o )
   return list;
 }
 
+static const void *
+dvb_mux_dvbs_class_pls_mode_get ( void *o )
+{
+  static const char *s;
+  dvb_mux_t *lm = o;
+  s = dvb_plsmode2str(lm->lm_tuning.dmc_fe_pls_mode);
+  return &s;
+}
+
+static int
+dvb_mux_dvbs_class_pls_mode_set ( void *o, const void *s )
+{
+  dvb_mux_t *lm = o;
+  lm->lm_tuning.dmc_fe_pls_mode = dvb_str2plsmode(s);
+  return 1;
+}
+
+static htsmsg_t *
+dvb_mux_dvbs_class_pls_mode_list ( void *o )
+{
+  htsmsg_t *list = htsmsg_create_list();
+  htsmsg_add_str(list, NULL, dvb_plsmode2str(DVB_PLS_ROOT));
+  htsmsg_add_str(list, NULL, dvb_plsmode2str(DVB_PLS_GOLD));
+  htsmsg_add_str(list, NULL, dvb_plsmode2str(DVB_PLS_COMBO));
+  return list;
+}
+
 #define dvb_mux_dvbs_class_delsys_get dvb_mux_class_delsys_get
 #define dvb_mux_dvbs_class_delsys_set dvb_mux_class_delsys_set
 
@@ -505,6 +539,29 @@ const idclass_t dvb_mux_dvbs_class =
       .get      = dvb_mux_dvbs_class_pilot_get,
       .list     = dvb_mux_dvbs_class_pilot_list,
     },
+    {
+      .type     = PT_INT,
+      .id       = "stream_id",
+      .name     = "ISI",
+      .off      = offsetof(dvb_mux_t, lm_tuning.dmc_fe_stream_id),
+      .def.i   = -1,
+    },
+    {
+      .type     = PT_STR,
+      .id       = "pls_mode",
+      .name     = "PLS MODE",
+      .set      = dvb_mux_dvbs_class_pls_mode_set,
+      .get      = dvb_mux_dvbs_class_pls_mode_get,
+      .list     = dvb_mux_dvbs_class_pls_mode_list,
+      .def.s    = "ROOT",
+    },
+    {
+      .type     = PT_U32,
+      .id       = "pls_code",
+      .name     = "PLS CODE",
+      .off      = offsetof(dvb_mux_t, lm_tuning.dmc_fe_pls_code),
+      .def.u32 = 1,
+    },
     {
       .type     = PT_STR,
       .id       = "orbital",
index 601b1e12303846fbee3cd2aedf16aab542e0d1a0..6404dc3b12f3335aa98499ef6fbaa492f8046d3b 100644 (file)
@@ -304,6 +304,7 @@ dvb_network_find_mux
     /* Reject if not same symbol rate (some tolerance due to changes and diff in NIT) */
     if (dvb_network_check_symbol_rate(lm, dmc, deltar)) continue;
 
+
     /* DVB-S extra checks */
     if (lm->lm_tuning.dmc_fe_type == DVB_TYPE_S) {
 
@@ -314,6 +315,9 @@ dvb_network_find_mux
       if (dvb_network_check_orbital_pos(lm, dmc)) continue;
     }
 
+    /* Same PLP/ISI */
+    if (lm->lm_tuning.dmc_fe_stream_id != dmc->dmc_fe_stream_id) continue;
+
     mm_alt = mm;
 
     /* Reject if not same ID */
@@ -453,6 +457,7 @@ dvb_network_create_mux
     save |= COMPAREN(dmc_fe_pilot);
     switch (dmc->dmc_fe_type) {
     case DVB_TYPE_T:
+      save |= COMPARE(dmc_fe_stream_id);
       save |= COMPAREN(u.dmc_fe_ofdm.bandwidth);
       save |= COMPAREN(u.dmc_fe_ofdm.code_rate_HP);
       save |= COMPAREN(u.dmc_fe_ofdm.code_rate_LP);
@@ -463,6 +468,9 @@ dvb_network_create_mux
     case DVB_TYPE_S:
       save |= COMPARE(u.dmc_fe_qpsk.polarisation);
       save |= COMPARE(u.dmc_fe_qpsk.symbol_rate);
+      save |= COMPARE(dmc_fe_stream_id);
+      save |= COMPAREN(dmc_fe_pls_mode);
+      save |= COMPAREN(dmc_fe_pls_code);
       save |= COMPAREN(u.dmc_fe_qpsk.fec_inner);
       break;
     case DVB_TYPE_C:
index cd6c2c96b0c2405f77a0b9c94c1fbc61f86b01ee..64df1d0395f05cdbab1b04c093ad82451eea049b 100644 (file)
@@ -131,18 +131,18 @@ scanfile_load_dvbt ( dvb_mux_conf_t *mux, const char *line )
   int r;
 
   if (*line == '2') {
-    unsigned int plp_id, system_id;
-    r = sscanf(line+1, "%u %s", &plp_id, bw);
-    if (r == 2 && plp_id < 1000 && strstr(bw, "MHz") == 0) {
+    unsigned int system_id;
+    r = sscanf(line+1, "%u %s", &mux->dmc_fe_stream_id, bw);
+    if (r == 2 && mux->dmc_fe_stream_id < 1000 && strstr(bw, "MHz") == 0) {
       r = sscanf(line+1, "%u %u %u %10s %10s %10s %10s %10s %10s %10s",
-                    &plp_id, &system_id, &mux->dmc_fe_freq, bw, fec, fec2, qam,
+                    &mux->dmc_fe_stream_id, &system_id, &mux->dmc_fe_freq, bw, fec, fec2, qam,
                      mode, guard, hier);
       if(r != 10) return 1;
     } else {
       r = sscanf(line+1, "%u %10s %10s %10s %10s %10s %10s %10s %u",
                     &mux->dmc_fe_freq, bw, fec, fec2, qam,
-                     mode, guard, hier, &plp_id);
-      if(r == 8) plp_id = 0; /* auto? */ else
+                     mode, guard, hier, &mux->dmc_fe_stream_id);
+      if(r == 8) mux->dmc_fe_stream_id = -1; else
       if(r != 9) return 1;
     }
     mux->dmc_fe_delsys = DVB_SYS_DVBT2;
@@ -176,9 +176,9 @@ scanfile_load_dvbs ( dvb_mux_conf_t *mux, const char *line )
     line++;
   }
 
-  r = sscanf(line, "%u %s %u %s %s %s",
+  r = sscanf(line, "%u %s %u %s %s %s %d %d %d",
                   &mux->dmc_fe_freq, pol, &mux->u.dmc_fe_qpsk.symbol_rate,
-             fec, rolloff, qam);
+             fec, rolloff, qam, &mux->dmc_fe_stream_id, &mux->dmc_fe_pls_code, (int*)&mux->dmc_fe_pls_mode);
   if (r < (4+v2)) return 1;
 
   mux->dmc_fe_type = DVB_TYPE_S;
@@ -188,6 +188,9 @@ scanfile_load_dvbs ( dvb_mux_conf_t *mux, const char *line )
     mux->dmc_fe_delsys     = DVB_SYS_DVBS2;
     if ((mux->dmc_fe_rolloff    = dvb_str2rolloff(rolloff)) == -1) return 1;
     if ((mux->dmc_fe_modulation = dvb_str2qam(qam))         == -1) return 1;
+    if (r < (4+v2+1)) mux->dmc_fe_stream_id = -1;
+    if (r < (4+v2+2)) mux->dmc_fe_pls_code = 1;
+    if (r < (4+v2+3)) mux->dmc_fe_pls_mode = 0;
   } else {
     mux->dmc_fe_delsys     = DVB_SYS_DVBS;
     mux->dmc_fe_rolloff    = DVB_ROLLOFF_35;
@@ -454,6 +457,8 @@ scanfile_load_dvbv5 ( scanfile_network_t *net, char *line, fb_file *fp )
     if ((x = htsmsg_get_str(l, "INVERSION")))
       if ((mux->dmc_fe_inversion = dvb_str2inver(x)) == -1)
         mux_fail(r, "wrong inversion '%s'", x);
+    if (htsmsg_get_s32(l, "STREAM_ID", &mux->dmc_fe_stream_id))
+      mux->dmc_fe_stream_id = -1;
 
   } else if (mux->dmc_fe_delsys == DVB_SYS_DVBS ||
              mux->dmc_fe_delsys == DVB_SYS_DVBS2) {
@@ -481,6 +486,17 @@ scanfile_load_dvbv5 ( scanfile_network_t *net, char *line, fb_file *fp )
     if ((x = htsmsg_get_str(l, "PILOT")))
       if ((mux->dmc_fe_pilot = dvb_str2rolloff(x)) == -1)
         mux_fail(r, "wrong pilot '%s'", x);
+    if (htsmsg_get_s32(l, "STREAM_ID", &r)) {
+      mux->dmc_fe_stream_id = -1;
+      mux->dmc_fe_pls_mode = 0;
+      mux->dmc_fe_pls_code = 1;
+    }
+    else {
+      mux->dmc_fe_stream_id = r&0xff;
+      mux->dmc_fe_pls_mode = (r>>26)&0x3;
+      mux->dmc_fe_pls_code = (r>>8)&0x3FFFF;
+    }
+
     if ((x = htsmsg_get_str(l, "POLARIZATION"))) {
       char pol[2];
       pol[0] = x[0]; pol[1] = '\0';