]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
[PR-177] Added preferred CA pid support
authorAndrew White <lan3620@mail.ru>
Sun, 25 Nov 2012 22:11:51 +0000 (02:11 +0400)
committerAdam Sutton <dev@adamsutton.me.uk>
Wed, 28 Nov 2012 09:49:33 +0000 (09:49 +0000)
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.

src/cwc.c
src/dvb/dvb_service.c
src/service.c
src/service.h
src/webui/extjs.c
src/webui/static/app/dvb.js

index 51b8f2e75de188d8ac66c7fb563bf62eb8af49cf..52a4489e74c3e381a5d9fa7014d164a31f74d58d 100644 (file)
--- a/src/cwc.c
+++ b/src/cwc.c
@@ -27,7 +27,6 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <ctype.h>
-
 #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 <openssl/des.h>
 
 /**
@@ -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;
index 82621227125d11f6719a2e7d4ab5acebd6fa211e..65b7fbf5e1a1348eecf5f00ad783568d7f6bf40e 100644 (file)
@@ -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;
 }
 
index 6548f10473251b7e72471c88922e8c91a5d819f3..e189ae1d9336ebbcc5b1f963ac40e26aaf66e7f3 100644 (file)
@@ -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;
index 11e39b5d96c213ad796dc54fef502465c988bb53..b6463fc05d6079d8f3bdd6e9179dd5cac7e8e322 100644 (file)
@@ -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);
index 10829e2e9fb64d32bc50176bf2804b58316e7a84..6355e2360e25440e7f65383efecfd8db121c0232 100644 (file)
@@ -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);
 
index 746ac7d6db0a8022a285e1e39c53f82bf01b72be..0f1b836f52ffcdfa479af2eb7c265b0b98c3dbf9 100644 (file)
@@ -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,