From: Jaroslav Kysela Date: Fri, 10 Nov 2017 09:05:03 +0000 (+0100) Subject: mpegts: add full DTMB network/mux support, issue #4717 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=10e6dbe99fcaffb4cbb7b0045fa5b577243d3d28;p=thirdparty%2Ftvheadend.git mpegts: add full DTMB network/mux support, issue #4717 --- diff --git a/src/input/mpegts/dvb.h b/src/input/mpegts/dvb.h index f169ffff4..cc0a92bb0 100644 --- a/src/input/mpegts/dvb.h +++ b/src/input/mpegts/dvb.h @@ -416,6 +416,7 @@ typedef enum dvb_fe_type { DVB_TYPE_ISDB_T, /* terrestrial - japan, brazil */ DVB_TYPE_ISDB_C, /* cable - japan, brazil */ DVB_TYPE_ISDB_S, /* satellite - japan, brazil */ + DVB_TYPE_DTMB, /* DTMB - china, cuba, hong kong, macau */ DVB_TYPE_DAB, /* digital radio (europe) */ DVB_TYPE_LAST = DVB_TYPE_DAB } dvb_fe_type_t; diff --git a/src/input/mpegts/dvb_support.c b/src/input/mpegts/dvb_support.c index d475c5449..360bf3818 100644 --- a/src/input/mpegts/dvb_support.c +++ b/src/input/mpegts/dvb_support.c @@ -728,7 +728,6 @@ dvb_delsys2type ( mpegts_network_t *ln, dvb_fe_delivery_system_t delsys ) case DVB_SYS_DVBT: case DVB_SYS_DVBT2: case DVB_SYS_TURBO: - case DVB_SYS_DTMB: return DVB_TYPE_T; case DVB_SYS_DVBS: case DVB_SYS_DVBS2: @@ -747,6 +746,8 @@ dvb_delsys2type ( mpegts_network_t *ln, dvb_fe_delivery_system_t delsys ) return DVB_TYPE_ISDB_C; case DVB_SYS_ISDBS: return DVB_TYPE_ISDB_S; + case DVB_SYS_DTMB: + return DVB_TYPE_DTMB; case DVB_SYS_DAB: return DVB_TYPE_DAB; default: diff --git a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c index 0504cbffd..2e8730231 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c @@ -453,6 +453,16 @@ const idclass_t linuxdvb_frontend_isdb_s_class = } }; +const idclass_t linuxdvb_frontend_dtmb_class = +{ + .ic_super = &linuxdvb_frontend_class, + .ic_class = "linuxdvb_frontend_dab", + .ic_caption = N_("TV Adapters - DTMB Frontend"), + .ic_properties = (const property_t[]){ + {} + } +}; + const idclass_t linuxdvb_frontend_dab_class = { .ic_super = &linuxdvb_frontend_class, @@ -1741,6 +1751,7 @@ linuxdvb_frontend_tune0 p.inversion = TR(inversion, inv_tbl, INVERSION_AUTO); switch (dmc->dmc_fe_type) { case DVB_TYPE_T: + case DVB_TYPE_DTMB: #define _OFDM(xyz) p.u.ofdm.xyz _OFDM(bandwidth) = TRU(ofdm.bandwidth, bw_tbl, BANDWIDTH_AUTO); _OFDM(code_rate_HP) = TRU(ofdm.code_rate_HP, fec_tbl, FEC_AUTO); @@ -1809,7 +1820,7 @@ linuxdvb_frontend_tune0 S2CMD(DTV_INVERSION, p.inversion); /* DVB-T */ - if (lfe->lfe_type == DVB_TYPE_T) { + if (lfe->lfe_type == DVB_TYPE_T || lfe->lfe_type == DVB_TYPE_DTMB) { S2CMD(DTV_BANDWIDTH_HZ, dvb_bandwidth(dmc->u.dmc_fe_ofdm.bandwidth)); #if DVB_VER_ATLEAST(5,1) S2CMD(DTV_CODE_RATE_HP, p.u.ofdm.code_rate_HP); @@ -2101,6 +2112,8 @@ linuxdvb_frontend_create idc = &linuxdvb_frontend_isdb_c_class; else if (type == DVB_TYPE_ISDB_S) idc = &linuxdvb_frontend_isdb_s_class; + else if (type == DVB_TYPE_DTMB) + idc = &linuxdvb_frontend_dtmb_class; else if (type == DVB_TYPE_DAB) idc = &linuxdvb_frontend_dab_class; else { diff --git a/src/input/mpegts/mpegts_dvb.h b/src/input/mpegts/mpegts_dvb.h index f22e8b0b9..43e163453 100644 --- a/src/input/mpegts/mpegts_dvb.h +++ b/src/input/mpegts/mpegts_dvb.h @@ -53,6 +53,7 @@ extern const idclass_t dvb_network_atsc_c_class; extern const idclass_t dvb_network_isdb_t_class; extern const idclass_t dvb_network_isdb_c_class; extern const idclass_t dvb_network_isdb_s_class; +extern const idclass_t dvb_network_dtmb_class; extern const idclass_t dvb_network_dab_class; void dvb_network_init ( void ); @@ -90,6 +91,7 @@ extern const idclass_t dvb_mux_atsc_c_class; extern const idclass_t dvb_mux_isdb_t_class; extern const idclass_t dvb_mux_isdb_c_class; extern const idclass_t dvb_mux_isdb_s_class; +extern const idclass_t dvb_mux_dtmb_class; extern const idclass_t dvb_mux_dab_class; dvb_mux_t *dvb_mux_create0 diff --git a/src/input/mpegts/mpegts_mux_dvb.c b/src/input/mpegts/mpegts_mux_dvb.c index 2b6be736f..668fe4d33 100644 --- a/src/input/mpegts/mpegts_mux_dvb.c +++ b/src/input/mpegts/mpegts_mux_dvb.c @@ -180,7 +180,6 @@ dvb_mux_dvbt_class_delsys_enum (void *o, const char *lang) htsmsg_add_str(list, NULL, dvb_delsys2str(DVB_SYS_DVBT)); htsmsg_add_str(list, NULL, dvb_delsys2str(DVB_SYS_DVBT2)); htsmsg_add_str(list, NULL, dvb_delsys2str(DVB_SYS_TURBO)); - htsmsg_add_str(list, NULL, dvb_delsys2str(DVB_SYS_DTMB)); return list; } @@ -853,6 +852,138 @@ const idclass_t dvb_mux_isdb_s_class = } }; +/* + * DTMB, fixme: review actually used parameters! + */ + +dvb_mux_class_X(dtmb, ofdm, bandwidth, bw, bw, + DVB_BANDWIDTH_AUTO, DVB_BANDWIDTH_10_MHZ, + DVB_BANDWIDTH_8_MHZ, DVB_BANDWIDTH_7_MHZ, + DVB_BANDWIDTH_6_MHZ, DVB_BANDWIDTH_5_MHZ, + DVB_BANDWIDTH_1_712_MHZ); +dvb_mux_class_R(dtmb, modulation, qam, qam, + DVB_MOD_QAM_AUTO, DVB_MOD_QPSK, DVB_MOD_QAM_16, + DVB_MOD_QAM_64, DVB_MOD_QAM_256); +dvb_mux_class_X(dtmb, ofdm, transmission_mode, mode, mode, + DVB_TRANSMISSION_MODE_AUTO, DVB_TRANSMISSION_MODE_32K, + DVB_TRANSMISSION_MODE_16K, DVB_TRANSMISSION_MODE_8K, + DVB_TRANSMISSION_MODE_2K, DVB_TRANSMISSION_MODE_1K); +dvb_mux_class_X(dtmb, ofdm, guard_interval, guard, guard, + DVB_GUARD_INTERVAL_AUTO, DVB_GUARD_INTERVAL_1_32, + DVB_GUARD_INTERVAL_1_16, DVB_GUARD_INTERVAL_1_8, + DVB_GUARD_INTERVAL_1_4, DVB_GUARD_INTERVAL_1_128, + DVB_GUARD_INTERVAL_19_128, DVB_GUARD_INTERVAL_19_256); +dvb_mux_class_X(dtmb, ofdm, hierarchy_information, hier, hier, + DVB_HIERARCHY_AUTO, DVB_HIERARCHY_NONE, + DVB_HIERARCHY_1, DVB_HIERARCHY_2, DVB_HIERARCHY_4); +dvb_mux_class_X(dtmb, ofdm, code_rate_HP, fechi, fechi, + DVB_FEC_AUTO, DVB_FEC_1_2, DVB_FEC_2_3, DVB_FEC_3_4, + DVB_FEC_3_5, DVB_FEC_4_5, DVB_FEC_5_6, DVB_FEC_7_8); +dvb_mux_class_X(dtmb, ofdm, code_rate_LP, feclo, feclo, + DVB_FEC_AUTO, DVB_FEC_1_2, DVB_FEC_2_3, DVB_FEC_3_4, + DVB_FEC_3_5, DVB_FEC_4_5, DVB_FEC_5_6, DVB_FEC_7_8); + +#define dvb_mux_dtmb_class_delsys_get dvb_mux_class_delsys_get +#define dvb_mux_dtmb_class_delsys_set dvb_mux_class_delsys_set + +static htsmsg_t * +dvb_mux_dtmb_class_delsys_enum (void *o, const char *lang) +{ + htsmsg_t *list = htsmsg_create_list(); + htsmsg_add_str(list, NULL, dvb_delsys2str(DVB_SYS_DTMB)); + return list; +} + +static int +dvb_mux_dtmb_class_frequency_set ( void *o, const void *v ) +{ + dvb_mux_t *lm = o; + uint32_t val = *(uint32_t *)v; + + if (val < 1000) + val *= 1000000; + else if (val < 1000000) + val *= 1000; + + if (val != lm->lm_tuning.dmc_fe_freq) { + lm->lm_tuning.dmc_fe_freq = val; + return 1; + } + return 0; +} + +const idclass_t dvb_mux_dtmb_class = +{ + .ic_super = &dvb_mux_class, + .ic_class = "dvb_mux_dtmb", + .ic_caption = N_("DTMB multiplex"), + .ic_properties = (const property_t[]){ + { + MUX_PROP_STR("delsys", N_("Delivery system"), dtmb, delsys, "DVBT"), + .desc = N_("The delivery system the mux uses. " + "Make sure that your tuner supports the delivery " + "system selected here."), + }, + { + .type = PT_U32, + .id = "frequency", + .name = N_("Frequency (Hz)"), + .desc = N_("The frequency of the mux (in Hertz)."), + .off = offsetof(dvb_mux_t, lm_tuning.dmc_fe_freq), + .set = dvb_mux_dtmb_class_frequency_set, + }, + { + MUX_PROP_STR("bandwidth", N_("Bandwidth"), dtmb, bw, N_("AUTO")), + .desc = N_("The bandwidth the mux uses. " + "If you're not sure of the value leave as AUTO " + "but be aware that tuning may fail as some drivers " + "do not like the AUTO setting."), + }, + { + MUX_PROP_STR("constellation", N_("Constellation"), dtmb, qam, N_("AUTO")), + .desc = N_("The COFDM modulation used by the mux. " + "If you're not sure of the value leave as AUTO."), + }, + { + MUX_PROP_STR("transmission_mode", N_("Transmission mode"), dtmb, mode, N_("AUTO")), + .desc = N_("The transmission/OFDM mode used by the mux. " + "If you're not sure of the value leave as AUTO " + "but be aware that tuning may fail as some drivers " + "do not like the AUTO setting."), + }, + { + MUX_PROP_STR("guard_interval", N_("Guard interval"), dtmb, guard, N_("AUTO")), + .desc = N_("The guard interval used by the mux. " + "If you're not sure of the value leave as AUTO."), + }, + { + MUX_PROP_STR("hierarchy", N_("Hierarchy"), dtmb, hier, N_("AUTO")), + .desc = N_("The hierarchical modulation used by the mux. " + "Most people will not need to change this setting."), + }, + { + MUX_PROP_STR("fec_hi", N_("FEC high"), dtmb, fechi, N_("AUTO")), + .desc = N_("The forward error correction high value. " + "Most people will not need to change this setting."), + }, + { + MUX_PROP_STR("fec_lo", N_("FEC low"), dtmb, feclo, N_("AUTO")), + .desc = N_("The forward error correction low value. " + "Most people will not need to change this setting."), + }, + { + .type = PT_INT, + .id = "plp_id", + .name = N_("PLP ID"), + .desc = N_("The physical layer pipe ID. " + "Most people will not need to change this setting."), + .off = offsetof(dvb_mux_t, lm_tuning.dmc_fe_stream_id), + .def.i = DVB_NO_STREAM_ID_FILTER, + }, + {} + } +}; + /* * DAB */ @@ -1011,6 +1142,9 @@ dvb_mux_create0 } else if (ln->ln_type == DVB_TYPE_ISDB_S) { idc = &dvb_mux_isdb_s_class; delsys = DVB_SYS_ISDBS; + } else if (ln->ln_type == DVB_TYPE_DTMB) { + idc = &dvb_mux_dtmb_class; + delsys = DVB_SYS_DTMB; } else if (ln->ln_type == DVB_TYPE_DAB) { idc = &dvb_mux_dab_class; delsys = DVB_SYS_DAB; diff --git a/src/input/mpegts/mpegts_network_dvb.c b/src/input/mpegts/mpegts_network_dvb.c index 9ef1e4839..88d5d6ad8 100644 --- a/src/input/mpegts/mpegts_network_dvb.c +++ b/src/input/mpegts/mpegts_network_dvb.c @@ -140,6 +140,8 @@ dvb_network_class_scanfile_list0 type = "isdb-c"; else if (clazz == &dvb_network_isdb_s_class) type = "isdb-s"; + else if (clazz == &dvb_network_dtmb_class) + type = "dtmb"; else if (clazz == &dvb_network_dab_class) type = "dab"; else @@ -174,6 +176,7 @@ SCANFILE_LIST(atsc_c); SCANFILE_LIST(isdb_t); SCANFILE_LIST(isdb_c); SCANFILE_LIST(isdb_s); +SCANFILE_LIST(dtmb); SCANFILE_LIST(dab); static const void * @@ -424,6 +427,29 @@ const idclass_t dvb_network_isdb_s_class = } }; +const idclass_t dvb_network_dtmb_class = +{ + .ic_super = &dvb_network_class, + .ic_class = "dvb_network_dtmb", + .ic_caption = N_("DTMB Network"), + .ic_properties = (const property_t[]) { + { + .type = PT_STR, + .id = "scanfile", + .name = N_("Pre-defined muxes"), + .desc = N_("Use a pre-defined list of DTMB muxes. " + "Note: these lists can sometimes be outdated and " + "may cause scanning to take longer than usual."), + .doc = prop_doc_predefinedmuxlist, + .set = dvb_network_class_scanfile_set, + .get = dvb_network_class_scanfile_get, + .list = dvb_network_class_scanfile_list_dtmb, + .opts = PO_NOSAVE, + }, + {} + } +}; + const idclass_t dvb_network_dab_class = { .ic_super = &dvb_network_class, @@ -465,6 +491,7 @@ dvb_network_check_symbol_rate( dvb_mux_t *lm, dvb_mux_conf_t *dmc, int deltar ) { switch (dmc->dmc_fe_type) { case DVB_TYPE_T: + case DVB_TYPE_DTMB: return dvb_network_check_bandwidth(lm->lm_tuning.u.dmc_fe_ofdm.bandwidth, dmc->u.dmc_fe_ofdm.bandwidth); case DVB_TYPE_C: @@ -607,6 +634,8 @@ dvb_network_mux_class return &dvb_mux_isdb_c_class; if (idnode_is_instance(&mn->mn_id, &dvb_network_isdb_s_class)) return &dvb_mux_isdb_s_class; + if (idnode_is_instance(&mn->mn_id, &dvb_network_dtmb_class)) + return &dvb_mux_dtmb_class; if (idnode_is_instance(&mn->mn_id, &dvb_network_dab_class)) return &dvb_mux_dab_class; return NULL; @@ -668,6 +697,7 @@ dvb_network_create_mux save |= cls == &dvb_mux_dvbs_class && dmc->dmc_fe_type == DVB_TYPE_S; save |= cls == &dvb_mux_atsc_t_class && dmc->dmc_fe_type == DVB_TYPE_ATSC_T; save |= cls == &dvb_mux_atsc_c_class && dmc->dmc_fe_type == DVB_TYPE_ATSC_C; + save |= cls == &dvb_mux_dtmb_class && dmc->dmc_fe_type == DVB_TYPE_DTMB; if (save && dmc->dmc_fe_type == DVB_TYPE_S) { satpos = dvb_network_get_orbital_pos(mn); /* do not allow to mix satellite positions */ @@ -737,6 +767,7 @@ dvb_network_create_mux save |= COMPAREN(dmc_fe_pilot, CBIT_PILOT); switch (dmc->dmc_fe_type) { case DVB_TYPE_T: + case DVB_TYPE_DTMB: save |= COMPARE(dmc_fe_stream_id, CBIT_STREAM_ID); save |= COMPAREN(u.dmc_fe_ofdm.bandwidth, CBIT_BANDWIDTH); save |= COMPAREN(u.dmc_fe_ofdm.hierarchy_information, CBIT_HIERARCHY); @@ -972,6 +1003,8 @@ const idclass_t *dvb_network_class_by_fe_type(dvb_fe_type_t type) return &dvb_network_isdb_c_class; else if (type == DVB_TYPE_ISDB_S) return &dvb_network_isdb_s_class; + else if (type == DVB_TYPE_DTMB) + return &dvb_network_dtmb_class; else if (type == DVB_TYPE_DAB) return &dvb_network_dab_class; @@ -996,6 +1029,8 @@ dvb_fe_type_t dvb_fe_type_by_network_class(const idclass_t *idc) return DVB_TYPE_ISDB_C; else if (idc == &dvb_network_isdb_s_class) return DVB_TYPE_ISDB_S; + else if (idc == &dvb_network_dtmb_class) + return DVB_TYPE_DTMB; else if (idc == &dvb_network_dab_class) return DVB_TYPE_DAB;