Add support for multiple CAIDs per PID
This commit is contained in:
parent
77ad2f6885
commit
d167cada79
7 changed files with 221 additions and 57 deletions
23
src/capmt.c
23
src/capmt.c
|
@ -411,6 +411,12 @@ capmt_table_input(struct th_descrambler *td, struct th_transport *t,
|
|||
capmt_t *capmt = ct->ct_capmt;
|
||||
int adapter_num = t->tht_dvb_mux_instance->tdmi_adapter->tda_adapter_num;
|
||||
|
||||
caid_t *c;
|
||||
|
||||
c = LIST_FIRST(&st->st_caids);
|
||||
if(c == NULL)
|
||||
return;
|
||||
|
||||
if(len > 4096)
|
||||
return;
|
||||
|
||||
|
@ -420,9 +426,9 @@ capmt_table_input(struct th_descrambler *td, struct th_transport *t,
|
|||
{
|
||||
/* ECM */
|
||||
if (ct->ct_caid_last == -1)
|
||||
ct->ct_caid_last = st->st_caid;
|
||||
ct->ct_caid_last = c->caid;
|
||||
|
||||
uint16_t caid = st->st_caid;
|
||||
uint16_t caid = c->caid;
|
||||
/* search ecmpid in list */
|
||||
capmt_caid_ecm_t *cce, *cce2;
|
||||
LIST_FOREACH(cce, &ct->ct_caid_ecm, cce_link)
|
||||
|
@ -432,11 +438,11 @@ capmt_table_input(struct th_descrambler *td, struct th_transport *t,
|
|||
if (!cce)
|
||||
{
|
||||
tvhlog(LOG_DEBUG, "capmt",
|
||||
"New caid 0x%04X for service \"%s\"", st->st_caid, t->tht_svcname);
|
||||
"New caid 0x%04X for service \"%s\"", c->caid, t->tht_svcname);
|
||||
|
||||
/* ecmpid not already seen, add it to list */
|
||||
cce = calloc(1, sizeof(capmt_caid_ecm_t));
|
||||
cce->cce_caid = st->st_caid;
|
||||
cce->cce_caid = c->caid;
|
||||
cce->cce_ecmpid = st->st_pid;
|
||||
LIST_INSERT_HEAD(&ct->ct_caid_ecm, cce, cce_link);
|
||||
}
|
||||
|
@ -619,15 +625,16 @@ capmt_transport_start(th_transport_t *t)
|
|||
ct->ct_seq = capmt->capmt_seq++;
|
||||
|
||||
LIST_FOREACH(st, &t->tht_components, st_link) {
|
||||
if (st->st_caid == 0)
|
||||
continue;
|
||||
caid_t *c = LIST_FIRST(&st->st_caids);
|
||||
if(c == NULL)
|
||||
continue;
|
||||
|
||||
tvhlog(LOG_DEBUG, "capmt",
|
||||
"New caid 0x%04X for service \"%s\"", st->st_caid, t->tht_svcname);
|
||||
"New caid 0x%04X for service \"%s\"", c->caid, t->tht_svcname);
|
||||
|
||||
/* add it to list */
|
||||
cce = calloc(1, sizeof(capmt_caid_ecm_t));
|
||||
cce->cce_caid = st->st_caid;
|
||||
cce->cce_caid = c->caid;
|
||||
cce->cce_ecmpid = st->st_pid;
|
||||
LIST_INSERT_HEAD(&ct->ct_caid_ecm, cce, cce_link);
|
||||
|
||||
|
|
25
src/cwc.c
25
src/cwc.c
|
@ -1063,19 +1063,25 @@ cwc_table_input(struct th_descrambler *td, struct th_transport *t,
|
|||
int section;
|
||||
ecm_section_t *es;
|
||||
char chaninfo[32];
|
||||
caid_t *c;
|
||||
|
||||
if(len > 4096)
|
||||
return;
|
||||
|
||||
if(cwc->cwc_caid != st->st_caid)
|
||||
return;
|
||||
|
||||
if(!verify_provider(cwc, st->st_providerid))
|
||||
return;
|
||||
|
||||
if((data[0] & 0xf0) != 0x80)
|
||||
return;
|
||||
|
||||
LIST_FOREACH(c, &st->st_caids, link) {
|
||||
if(cwc->cwc_caid != c->caid)
|
||||
break;
|
||||
}
|
||||
|
||||
if(c == NULL)
|
||||
return;
|
||||
|
||||
if(!verify_provider(cwc, c->providerid))
|
||||
return;
|
||||
|
||||
switch(data[0]) {
|
||||
case 0x80:
|
||||
case 0x81:
|
||||
|
@ -1216,10 +1222,13 @@ static inline th_stream_t *
|
|||
cwc_find_stream_by_caid(th_transport_t *t, int caid)
|
||||
{
|
||||
th_stream_t *st;
|
||||
caid_t *c;
|
||||
|
||||
LIST_FOREACH(st, &t->tht_components, st_link) {
|
||||
if(st->st_caid == caid)
|
||||
return st;
|
||||
LIST_FOREACH(c, &st->st_caids, link) {
|
||||
if(c->caid == caid)
|
||||
return st;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1076,6 +1076,7 @@ dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src)
|
|||
th_dvb_mux_instance_t *tdmi_dst;
|
||||
th_transport_t *t_src, *t_dst;
|
||||
th_stream_t *st_src, *st_dst;
|
||||
caid_t *caid_src, *caid_dst;
|
||||
|
||||
tdmi_dst = dvb_mux_create(dst,
|
||||
&tdmi_src->tdmi_conf,
|
||||
|
@ -1120,7 +1121,15 @@ dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src)
|
|||
|
||||
memcpy(st_dst->st_lang, st_src->st_lang, 4);
|
||||
st_dst->st_frame_duration = st_src->st_frame_duration;
|
||||
st_dst->st_caid = st_src->st_caid;
|
||||
|
||||
LIST_FOREACH(caid_src, &st_src->st_caids, link) {
|
||||
caid_dst = malloc(sizeof(caid_t));
|
||||
|
||||
caid_dst->caid = caid_src->caid;
|
||||
caid_dst->providerid = caid_src->providerid;
|
||||
caid_dst->delete_me = 0;
|
||||
LIST_INSERT_HEAD(&st_dst->st_caids, caid_dst, link);
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&t_dst->tht_stream_mutex);
|
||||
|
|
173
src/psi.c
173
src/psi.c
|
@ -221,7 +221,7 @@ psi_build_pat(th_transport_t *t, uint8_t *buf, int maxlen, int pmtpid)
|
|||
#define PMT_UPDATE_NEW_CAID 0x100
|
||||
#define PMT_UPDATE_CA_PROVIDER_CHANGE 0x200
|
||||
#define PMT_UPDATE_PARENT_PID 0x400
|
||||
|
||||
#define PMT_UPDATE_CAID_DELETED 0x800
|
||||
|
||||
/**
|
||||
* Add a CA descriptor
|
||||
|
@ -230,6 +230,7 @@ static int
|
|||
psi_desc_add_ca(th_transport_t *t, uint16_t caid, uint32_t provid, uint16_t pid)
|
||||
{
|
||||
th_stream_t *st;
|
||||
caid_t *c;
|
||||
int r = 0;
|
||||
|
||||
if((st = transport_stream_find(t, pid)) == NULL) {
|
||||
|
@ -239,16 +240,26 @@ psi_desc_add_ca(th_transport_t *t, uint16_t caid, uint32_t provid, uint16_t pid)
|
|||
|
||||
st->st_delete_me = 0;
|
||||
|
||||
if(st->st_caid != caid) {
|
||||
st->st_caid = caid;
|
||||
r |= PMT_UPDATE_NEW_CAID;
|
||||
LIST_FOREACH(c, &st->st_caids, link) {
|
||||
if(c->caid == caid) {
|
||||
c->delete_me = 0;
|
||||
|
||||
if(c->providerid != provid) {
|
||||
c->providerid = provid;
|
||||
r |= PMT_UPDATE_CA_PROVIDER_CHANGE;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if(st->st_providerid != provid) {
|
||||
st->st_providerid = provid;
|
||||
r |= PMT_UPDATE_CA_PROVIDER_CHANGE;
|
||||
}
|
||||
c = malloc(sizeof(caid_t));
|
||||
|
||||
c->caid = caid;
|
||||
c->providerid = provid;
|
||||
|
||||
c->delete_me = 0;
|
||||
LIST_INSERT_HEAD(&st->st_caids, c, link);
|
||||
r |= PMT_UPDATE_NEW_CAID;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -259,11 +270,18 @@ static int
|
|||
psi_desc_ca(th_transport_t *t, const uint8_t *buffer, int size)
|
||||
{
|
||||
int r = 0;
|
||||
int i = 0;
|
||||
int i;
|
||||
uint32_t provid = 0;
|
||||
uint16_t caid = (buffer[0] << 8) | buffer[1];
|
||||
uint16_t pid = ((buffer[2]&0x1F) << 8) | buffer[3];
|
||||
|
||||
#if 0
|
||||
printf("CA_DESC: ");
|
||||
for(i = 0; i < size; i++)
|
||||
printf("%02x.", buffer[i]);
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
switch (caid & 0xFF00) {
|
||||
case 0x0100: // SECA/Mediaguard
|
||||
provid = (buffer[4] << 8) | buffer[5];
|
||||
|
@ -365,6 +383,7 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
int composition_id;
|
||||
int ancillary_id;
|
||||
int version;
|
||||
caid_t *c, *cn;
|
||||
|
||||
if(len < 9)
|
||||
return -1;
|
||||
|
@ -396,10 +415,16 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
len -= 9;
|
||||
|
||||
/* Mark all streams for deletion */
|
||||
if(delete)
|
||||
LIST_FOREACH(st, &t->tht_components, st_link)
|
||||
if(delete) {
|
||||
LIST_FOREACH(st, &t->tht_components, st_link) {
|
||||
st->st_delete_me = 1;
|
||||
|
||||
LIST_FOREACH(c, &st->st_caids, link)
|
||||
c->delete_me = 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
while(dllen > 1) {
|
||||
dtag = ptr[0];
|
||||
dlen = ptr[1];
|
||||
|
@ -555,6 +580,17 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
/* Scan again to see if any streams should be deleted */
|
||||
for(st = LIST_FIRST(&t->tht_components); st != NULL; st = next) {
|
||||
next = LIST_NEXT(st, st_link);
|
||||
|
||||
for(c = LIST_FIRST(&st->st_caids); c != NULL; c = cn) {
|
||||
cn = LIST_NEXT(c, link);
|
||||
if(c->delete_me) {
|
||||
LIST_REMOVE(c, link);
|
||||
free(c);
|
||||
update |= PMT_UPDATE_CAID_DELETED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(st->st_delete_me) {
|
||||
transport_stream_destroy(t, st);
|
||||
update |= PMT_UPDATE_STREAM_DELETED;
|
||||
|
@ -563,7 +599,7 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
|
||||
if(update) {
|
||||
tvhlog(LOG_DEBUG, "PSI", "Transport \"%s\" PMT (version %d) updated"
|
||||
"%s%s%s%s%s%s%s%s%s%s%s",
|
||||
"%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
transport_nicename(t), version,
|
||||
update&PMT_UPDATE_PCR ? ", PCR PID changed":"",
|
||||
update&PMT_UPDATE_NEW_STREAM ? ", New elementary stream":"",
|
||||
|
@ -575,11 +611,19 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid,
|
|||
update&PMT_UPDATE_NEW_CA_STREAM ? ", New CA stream":"",
|
||||
update&PMT_UPDATE_NEW_CAID ? ", New CAID":"",
|
||||
update&PMT_UPDATE_CA_PROVIDER_CHANGE? ", CA provider changed":"",
|
||||
update&PMT_UPDATE_PARENT_PID ? ", Parent PID changed":"");
|
||||
update&PMT_UPDATE_PARENT_PID ? ", Parent PID changed":"",
|
||||
update&PMT_UPDATE_CAID_DELETED ? ", CAID deleted":"");
|
||||
|
||||
transport_request_save(t);
|
||||
if(t->tht_status == TRANSPORT_RUNNING)
|
||||
transport_restart(t, had_components);
|
||||
|
||||
// Only restart if something that our clients worry about did change
|
||||
if(update & !(PMT_UPDATE_NEW_CA_STREAM |
|
||||
PMT_UPDATE_NEW_CAID |
|
||||
PMT_UPDATE_CA_PROVIDER_CHANGE |
|
||||
PMT_UPDATE_CAID_DELETED)) {
|
||||
if(t->tht_status == TRANSPORT_RUNNING)
|
||||
transport_restart(t, had_components);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -848,11 +892,20 @@ psi_save_transport_settings(htsmsg_t *m, th_transport_t *t)
|
|||
htsmsg_add_str(sub, "language", st->st_lang);
|
||||
|
||||
if(st->st_type == SCT_CA) {
|
||||
htsmsg_add_str(sub, "caid", psi_caid2name(st->st_caid));
|
||||
htsmsg_add_u32(sub, "caidnum", st->st_caid);
|
||||
|
||||
if(st->st_providerid)
|
||||
htsmsg_add_u32(sub, "caproviderid", st->st_providerid);
|
||||
caid_t *c;
|
||||
htsmsg_t *v = htsmsg_create_list();
|
||||
|
||||
LIST_FOREACH(c, &st->st_caids, link) {
|
||||
htsmsg_t *caid = htsmsg_create_map();
|
||||
|
||||
htsmsg_add_u32(caid, "caid", c->caid);
|
||||
if(c->providerid)
|
||||
htsmsg_add_u32(caid, "providerid", c->providerid);
|
||||
htsmsg_add_msg(v, NULL, caid);
|
||||
}
|
||||
|
||||
htsmsg_add_msg(sub, "caidlist", v);
|
||||
}
|
||||
|
||||
if(st->st_type == SCT_DVBSUB) {
|
||||
|
@ -871,6 +924,74 @@ psi_save_transport_settings(htsmsg_t *m, th_transport_t *t)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
add_caid(th_stream_t *st, uint16_t caid, uint32_t providerid)
|
||||
{
|
||||
caid_t *c = malloc(sizeof(caid_t));
|
||||
c->caid = caid;
|
||||
c->providerid = providerid;
|
||||
c->delete_me = 0;
|
||||
LIST_INSERT_HEAD(&st->st_caids, c, link);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
load_legacy_caid(htsmsg_t *c, th_stream_t *st)
|
||||
{
|
||||
uint32_t a, b;
|
||||
const char *v;
|
||||
|
||||
if(htsmsg_get_u32(c, "caproviderid", &b))
|
||||
b = 0;
|
||||
|
||||
if(htsmsg_get_u32(c, "caidnum", &a)) {
|
||||
if((v = htsmsg_get_str(c, "caid")) != NULL) {
|
||||
int i = str2val(v, caidnametab);
|
||||
a = i < 0 ? strtol(v, NULL, 0) : i;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
add_caid(st, a, b);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
load_caid(htsmsg_t *m, th_stream_t *st)
|
||||
{
|
||||
htsmsg_field_t *f;
|
||||
htsmsg_t *c, *v = htsmsg_get_list(m, "caidlist");
|
||||
uint32_t a, b;
|
||||
|
||||
if(v == NULL)
|
||||
return;
|
||||
|
||||
HTSMSG_FOREACH(f, v) {
|
||||
if((c = htsmsg_get_map_by_field(f)) == NULL)
|
||||
continue;
|
||||
|
||||
if(htsmsg_get_u32(c, "caid", &a))
|
||||
continue;
|
||||
|
||||
if(htsmsg_get_u32(c, "providerid", &b))
|
||||
b = 0;
|
||||
|
||||
add_caid(st, a, b);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Load transport info from htsmsg
|
||||
*/
|
||||
|
@ -879,11 +1000,10 @@ psi_load_transport_settings(htsmsg_t *m, th_transport_t *t)
|
|||
{
|
||||
htsmsg_t *c;
|
||||
htsmsg_field_t *f;
|
||||
uint32_t u32;
|
||||
uint32_t u32, pid;
|
||||
th_stream_t *st;
|
||||
streaming_component_type_t type;
|
||||
const char *v;
|
||||
uint32_t pid;
|
||||
|
||||
if(!htsmsg_get_u32(m, "pcr", &u32))
|
||||
t->tht_pcr_pid = u32;
|
||||
|
@ -919,14 +1039,9 @@ psi_load_transport_settings(htsmsg_t *m, th_transport_t *t)
|
|||
if(!htsmsg_get_u32(c, "frameduration", &u32))
|
||||
st->st_frame_duration = u32;
|
||||
|
||||
if(!htsmsg_get_u32(c, "caidnum", &u32)) {
|
||||
st->st_caid = u32;
|
||||
} else if((v = htsmsg_get_str(c, "caid")) != NULL) {
|
||||
int i = str2val(v, caidnametab);
|
||||
st->st_caid = i < 0 ? strtol(v, NULL, 0) : i;
|
||||
}
|
||||
|
||||
htsmsg_get_u32(c, "caproviderid", &st->st_providerid);
|
||||
|
||||
load_legacy_caid(c, st);
|
||||
load_caid(c, st);
|
||||
|
||||
if(type == SCT_DVBSUB) {
|
||||
if(!htsmsg_get_u32(c, "compositionid", &u32))
|
||||
|
|
19
src/tvhead.h
19
src/tvhead.h
|
@ -330,6 +330,19 @@ typedef void (pid_section_callback_t)(struct th_transport *t,
|
|||
struct th_stream *pi,
|
||||
const uint8_t *section, int section_len);
|
||||
|
||||
LIST_HEAD(caid_list, caid);
|
||||
/**
|
||||
*
|
||||
*/
|
||||
typedef struct caid {
|
||||
LIST_ENTRY(caid) link;
|
||||
|
||||
uint8_t delete_me;
|
||||
uint16_t caid;
|
||||
uint32_t providerid;
|
||||
|
||||
} caid_t;
|
||||
|
||||
/*
|
||||
* Stream, one media component for a transport.
|
||||
*
|
||||
|
@ -419,10 +432,8 @@ typedef struct th_stream {
|
|||
|
||||
struct th_pktref_queue st_durationq;
|
||||
|
||||
/* ca id for this stream */
|
||||
|
||||
uint16_t st_caid;
|
||||
uint32_t st_providerid;
|
||||
/* CA ID's on this stream */
|
||||
struct caid_list st_caids;
|
||||
|
||||
/* Remuxing information */
|
||||
AVRational st_tb;
|
||||
|
|
|
@ -1053,7 +1053,8 @@ extjs_servicedetails(http_connection_t *hc,
|
|||
htsmsg_t *out, *streams, *c;
|
||||
th_transport_t *t;
|
||||
th_stream_t *st;
|
||||
char buf[40];
|
||||
caid_t *caid;
|
||||
char buf[128];
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
|
@ -1077,8 +1078,14 @@ extjs_servicedetails(http_connection_t *hc,
|
|||
break;
|
||||
|
||||
case SCT_CA:
|
||||
snprintf(buf, sizeof(buf), "%s (0x%04x)",
|
||||
psi_caid2name(st->st_caid), st->st_caid);
|
||||
buf[0] = 0;
|
||||
|
||||
LIST_FOREACH(caid, &st->st_caids, link) {
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
|
||||
"%s (0x%04x) ",
|
||||
psi_caid2name(caid->caid), caid->caid);
|
||||
}
|
||||
|
||||
htsmsg_add_str(c, "details", buf);
|
||||
break;
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "access.h"
|
||||
#include "epg.h"
|
||||
#include "xmltv.h"
|
||||
#include "psi.h"
|
||||
#if ENABLE_LINUXDVB
|
||||
#include "dvr/dvr.h"
|
||||
#include "dvb/dvb.h"
|
||||
|
@ -106,13 +107,18 @@ dumptransports(htsbuf_queue_t *hq, struct th_transport_list *l, int indent)
|
|||
indent + 4, "");
|
||||
|
||||
LIST_FOREACH(st, &t->tht_components, st_link) {
|
||||
htsbuf_qprintf(hq, "%*.s%-16s %-5d %-5d %-5s %04x %08x\n", indent + 4, "",
|
||||
caid_t *caid;
|
||||
htsbuf_qprintf(hq, "%*.s%-16s %-5d %-5d %-5s\n", indent + 4, "",
|
||||
streaming_component_type2txt(st->st_type),
|
||||
st->st_index,
|
||||
st->st_pid,
|
||||
st->st_lang[0] ? st->st_lang : "",
|
||||
st->st_caid,
|
||||
st->st_providerid);
|
||||
st->st_lang[0] ? st->st_lang : "");
|
||||
LIST_FOREACH(caid, &st->st_caids, link) {
|
||||
htsbuf_qprintf(hq, "%*.sCAID %04x (%s) %08x\n", indent + 6, "",
|
||||
caid->caid,
|
||||
psi_caid2name(caid->caid),
|
||||
caid->providerid);
|
||||
}
|
||||
}
|
||||
|
||||
htsbuf_qprintf(hq, "\n");
|
||||
|
|
Loading…
Add table
Reference in a new issue