dvb_psi: nit,sdt,vct callbacks - operate on all muxes with same tsid, fixes #2605

This commit is contained in:
Jaroslav Kysela 2015-01-11 21:43:22 +01:00
parent f5c8e4ce86
commit eed4d8cdc5

View 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;
char buf[128];
/* 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;
mpegts_mux_nice_name(mm, buf, sizeof(buf));
/* ID */
tvhdebug("sdt", "onid %04X (%d) tsid %04X (%d)", onid, onid, tsid, tsid);
/* 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;
if (mm->mm_tsid == tsid) {
/* Find the service */
if (!(s = mpegts_service_find(mm, sid, 0, 1, &save)))
continue;
/* 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;
}
/* 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: