From: Andrew White Date: Sun, 25 Nov 2012 22:11:51 +0000 (+0400) Subject: [PR-177] Added preferred CA pid support X-Git-Tag: v3.5~255 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=88067f869e33572b6d0c683c5c63f72edd139076;p=thirdparty%2Ftvheadend.git [PR-177] Added preferred CA pid support Added prefrerred CA pid field in user interface and use field value to store ECM only from stream which is answer ok. Field could be refreshed by program or manually. --- diff --git a/src/cwc.c b/src/cwc.c index 51b8f2e75..52a4489e7 100644 --- a/src/cwc.c +++ b/src/cwc.c @@ -27,7 +27,6 @@ #include #include #include - #include "tvheadend.h" #include "tcp.h" #include "psi.h" @@ -38,7 +37,7 @@ #include "atomic.h" #include "dtable.h" #include "subscriptions.h" - +#include "service.h" #include /** @@ -754,9 +753,9 @@ handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg, int len, int seq) { service_t *t = ct->cs_service; + ecm_pid_t *ep, *epn; cwc_service_t *ct2; cwc_t *cwc2; - ecm_pid_t *ep; char chaninfo[32]; int i; int64_t delay = (getmonoclock() - es->es_time) / 1000LL; // in ms @@ -773,9 +772,6 @@ handle_ecm_reply(cwc_service_t *ct, ecm_section_t *es, uint8_t *msg, /* ERROR */ - if(ct->cs_okchannel == es->es_channel) - ct->cs_okchannel = -1; - if (es->es_nok < 3) es->es_nok++; @@ -829,6 +825,11 @@ forbid: } else { ct->cs_okchannel = es->es_channel; + tvhlog(LOG_DEBUG, "cwc", "es->es_nok %d t->tht_prefcapid %d", es->es_nok, t->s_prefcapid); + if(es->es_nok == 1 || t->s_prefcapid == 0) { + t->s_prefcapid = ct->cs_okchannel; + service_request_save(t, 0); + } es->es_nok = 0; tvhlog(LOG_DEBUG, "cwc", @@ -865,6 +866,22 @@ forbid: ct->cs_keystate = CS_RESOLVED; memcpy(ct->cs_cw, msg + 3, 16); ct->cs_pending_cw_update = 1; + + ep = LIST_FIRST(&ct->cs_pids); + while(ep != NULL) { + if (ct->cs_okchannel == ep->ep_pid) { + ep = LIST_NEXT(ep, ep_link); + } + else { + epn = LIST_NEXT(ep, ep_link); + for(i = 0; i < 256; i++) + free(ep->ep_sections[i]); + LIST_REMOVE(ep, ep_link); + tvhlog(LOG_WARNING, "cwc", "Delete ECMpid %d", ep->ep_pid); + free(ep); + ep = epn; + } + } } } @@ -902,6 +919,10 @@ cwc_running_reply(cwc_t *cwc, uint8_t msgtype, uint8_t *msg, int len) } } tvhlog(LOG_WARNING, "cwc", "Got unexpected ECM reply (seqno: %d)", seq); + LIST_FOREACH(ct, &cwc->cwc_services, cs_link) { + tvhlog(LOG_DEBUG, "cwc", "After got unexpected (ct->cs_okchannel: %d)", ct->cs_okchannel); + if (ct->cs_okchannel == -3) ct->cs_okchannel = -2; + } break; } return 0; @@ -1592,9 +1613,28 @@ cwc_table_input(struct th_descrambler *td, struct service *t, } if(ep == NULL) { - ep = calloc(1, sizeof(ecm_pid_t)); - ep->ep_pid = st->es_pid; - LIST_INSERT_HEAD(&ct->cs_pids, ep, ep_link); + if (ct->cs_okchannel == -2) { + t->s_prefcapid = 0; + ct->cs_okchannel = -1; + tvhlog(LOG_DEBUG, "cwc", "Insert after unexpected reply"); + } + + if (ct->cs_okchannel == -3 && t->s_prefcapid == st->es_pid) { + ep = calloc(1, sizeof(ecm_pid_t)); + ep->ep_pid = t->s_prefcapid; + LIST_INSERT_HEAD(&ct->cs_pids, ep, ep_link); + tvhlog(LOG_DEBUG, "cwc", "Insert only one new ECM channel %d for service id %d", t->s_prefcapid, sid); + } + + if (ct->cs_okchannel == -1 || (ct->cs_okchannel == -3 && t->s_prefcapid == 0)) { + ep = calloc(1, sizeof(ecm_pid_t)); + ep->ep_pid = st->es_pid; + LIST_INSERT_HEAD(&ct->cs_pids, ep, ep_link); + tvhlog(LOG_DEBUG, "cwc", "Insert new ECM channel %d", st->es_pid); + } + else { + return; + } } @@ -1626,6 +1666,9 @@ cwc_table_input(struct th_descrambler *td, struct service *t, section = 0; } + channel = st->es_pid; + snprintf(chaninfo, sizeof(chaninfo), " (channel %d)", channel); + if(ep->ep_sections[section] == NULL) ep->ep_sections[section] = calloc(1, sizeof(ecm_section_t)); @@ -1650,7 +1693,7 @@ cwc_table_input(struct th_descrambler *td, struct service *t, memcpy(es->es_ecm, data, len); es->es_ecmsize = len; - if(ct->cs_okchannel != -1 && channel != -1 && + if(ct->cs_okchannel >= 0 && channel != -1 && ct->cs_okchannel != channel) { tvhlog(LOG_DEBUG, "cwc", "Filtering ECM channel %d", channel); return; @@ -1988,7 +2031,7 @@ cwc_service_start(service_t *t) ct->cs_keys = get_key_struct(); ct->cs_cwc = cwc; ct->cs_service = t; - ct->cs_okchannel = -1; + ct->cs_okchannel = -3; td = &ct->cs_head; td->td_stop = cwc_service_destroy; diff --git a/src/dvb/dvb_service.c b/src/dvb/dvb_service.c index 826212271..65b7fbf5e 100644 --- a/src/dvb/dvb_service.c +++ b/src/dvb/dvb_service.c @@ -259,6 +259,10 @@ dvb_service_load(th_dvb_mux_instance_t *tdmi, const char *tdmi_identifier) if(s && u32) service_map_channel(t, channel_find_by_name(s, 1, 0), 0); + if(htsmsg_get_u32(c, "prefcapid", &u32)) + u32 = 0; + t->s_prefcapid = u32; + /* HACK - force save for old config */ if(old) dvb_service_save(t); @@ -471,6 +475,8 @@ dvb_service_build_msg(service_t *t) htsmsg_add_u32(m, "dvb_eit_enable", t->s_dvb_eit_enable); + htsmsg_add_u32(m, "prefcapid", t->s_prefcapid); + return m; } diff --git a/src/service.c b/src/service.c index 6548f1047..e189ae1d9 100644 --- a/src/service.c +++ b/src/service.c @@ -933,6 +933,15 @@ service_set_enable(service_t *t, int enabled) subscription_reschedule(); } +void +service_set_prefcapid(service_t *t, uint32_t prefcapid) +{ + if(t->s_prefcapid == prefcapid) + return; + + t->s_prefcapid = prefcapid; + t->s_config_save(t); +} static pthread_mutex_t pending_save_mutex; static pthread_cond_t pending_save_cond; diff --git a/src/service.h b/src/service.h index 11e39b5d9..b6463fc05 100644 --- a/src/service.h +++ b/src/service.h @@ -474,6 +474,7 @@ typedef struct service { int s_scrambled; int s_scrambled_seen; int s_caid; + uint16_t s_prefcapid; /** * PCR drift compensation. This should really be per-packet. @@ -597,6 +598,8 @@ void service_set_dvb_charset(service_t *t, const char *dvb_charset); void service_set_dvb_eit_enable(service_t *t, int dvb_eit_enable); +void service_set_prefcapid(service_t *t, uint32_t prefcapid); + int service_is_primary_epg (service_t *t); htsmsg_t *servicetype_list (void); diff --git a/src/webui/extjs.c b/src/webui/extjs.c index 10829e2e9..6355e2360 100644 --- a/src/webui/extjs.c +++ b/src/webui/extjs.c @@ -1469,6 +1469,9 @@ service_update(htsmsg_t *in) if((chname = htsmsg_get_str(c, "channelname")) != NULL) service_map_channel(t, channel_find_by_name(chname, 1, 0), 1); + if(!htsmsg_get_u32(c, "prefcapid", &u32)) + service_set_prefcapid(t, u32); + if((dvb_charset = htsmsg_get_str(c, "dvb_charset")) != NULL) service_set_dvb_charset(t, dvb_charset); @@ -1800,6 +1803,9 @@ extjs_service_update(htsmsg_t *in) if(!htsmsg_get_u32(c, "enabled", &u32)) service_set_enable(t, u32); + if(!htsmsg_get_u32(c, "prefcapid", &u32)) + service_set_prefcapid(t, u32); + if((chname = htsmsg_get_str(c, "channelname")) != NULL) service_map_channel(t, channel_find_by_name(chname, 1, 0), 1); diff --git a/src/webui/static/app/dvb.js b/src/webui/static/app/dvb.js index 746ac7d6d..0f1b836f5 100644 --- a/src/webui/static/app/dvb.js +++ b/src/webui/static/app/dvb.js @@ -506,6 +506,11 @@ tvheadend.dvb_services = function(adapterId) { dataIndex : 'sid', width : 50, hidden : true + }, { + header: "Preffered CA pid", + dataIndex: 'prefcapid', + width: 50, + editor: new fm.TextField({allowBlank: true}) }, { header : "PMT PID", dataIndex : 'pmt', @@ -521,7 +526,7 @@ tvheadend.dvb_services = function(adapterId) { var store = new Ext.data.JsonStore({ root : 'entries', fields : Ext.data.Record.create([ 'id', 'enabled', 'type', 'sid', 'pmt', - 'pcr', 'svcname', 'network', 'provider', 'mux', 'channelname', + 'pcr', 'svcname', 'network', 'provider', 'mux', 'channelname', 'prefcapid', 'dvb_charset', 'dvb_eit_enable' ]), url : "dvb/services/" + adapterId, autoLoad : true,