]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
Add support for adding multiple services to DD CI
authorJasmin Jessich <jasmin@anw.at>
Sun, 18 Feb 2018 02:47:22 +0000 (03:47 +0100)
committerJaroslav Kysela <perex@perex.cz>
Sun, 25 Feb 2018 17:58:17 +0000 (18:58 +0100)
New functions linuxdvb_ddci_unassign and linuxdvb_ddci_do_not_assign.
Use a services list to store all assigned services.
Also store the mux/input in case of the first assigned service to allow
adding further services with only the same mux/input.
In linuxdvb_ddci_read_thread use mpegts_input_postdemux to deliver the
decrypted stream to the matching service(s).
linuxdvb_ddci_is_assigned renamed to linuxdvb_ddci_do_not_assign, which
will check if the DD CI CAM shall be assigned to a service or not. This
will now allow to use DD CI for all services of the same transponder
(mux).
Remove unused function linuxdvb_ddci_require_descramble.

Signed-off-by: Jasmin Jessich <jasmin@anw.at>
src/descrambler/dvbcam.c
src/input/mpegts/linuxdvb/linuxdvb_ddci.c
src/input/mpegts/linuxdvb/linuxdvb_private.h

index 0bba68e02d008bd33cbfc08b91485b2f2156b34b..53d02634ec858eba5bcf72e662af15e705619fd8 100644 (file)
@@ -138,7 +138,7 @@ dvbcam_unregister_ddci(dvbcam_active_cam_t *ac, dvbcam_active_service_t *as)
 
     /* unassign the service from the DD CI CAM */
     as->lddci = NULL;
-    linuxdvb_ddci_assign(lddci, NULL);
+    linuxdvb_ddci_unassign(lddci, t);
     if (dr) {
       dr->dr_descrambler = NULL;
       dr->dr_descramble = NULL;
@@ -498,12 +498,12 @@ dvbcam_service_start(caclient_t *cac, service_t *t)
             /* limit the concurrent service decoders per CAM */
             if (dc->limit > 0 && ac->allocated_programs >= dc->limit)
               continue;
-  #if ENABLE_DDCI
-            /* currently we allow only one service per DD CI */
+#if ENABLE_DDCI
             lcat = ac->ca->lca_transport;
-            if (lcat->lddci && linuxdvb_ddci_is_assigned(lcat->lddci))
+            if (lcat->lddci && linuxdvb_ddci_do_not_assign(lcat->lddci, t,
+                                                           dc->multi))
               continue;
-  #endif
+#endif
             tvhtrace(LS_DVBCAM, "%s/%p: match CAID %04X PID %d (%04X)",
                                 ac->ca->lca_name, t, c->caid, c->pid, c->pid);
             goto end_of_search_for_cam;
index f1cefb6125c86bef12cf3fc71bbb89bf45848471..712f499352bacef330aa3e22a5fdfba2057fc18a 100644 (file)
@@ -104,8 +104,12 @@ struct linuxdvb_ddci
   linuxdvb_ddci_wr_thread_t  lddci_wr_thread;
   linuxdvb_ddci_rd_thread_t  lddci_rd_thread;
 
-  /* currently we use a fix assignment to one single service */
-  service_t                 *t;   /* associated service */
+  /* list of services assigned to this DD CI instance */
+  idnode_set_t               *lddci_services;
+  /* the same mux used for all services */
+  mpegts_mux_t               *lddci_mm;
+  /* the same input used for all services */
+  mpegts_input_t             *lddci_mi;
 };
 
 
@@ -619,8 +623,7 @@ linuxdvb_ddci_read_thread ( void *arg )
   tvhtrace(LS_DDCI, "CAM %s read thread started", ci_id);
   linuxdvb_ddci_thread_signal(ddci_thread);
   while (tvheadend_is_running() && !ddci_thread->lddci_thread_stop) {
-    service_t *t;
-    int nfds, num_pkg, clr_stat = 0, pkg_chk = 0, scrambled = 0;
+    int nfds, num_pkg, pkg_chk = 0, scrambled = 0;
     ssize_t n;
 
     nfds = tvhpoll_wait(efd, ev, 1, 150);
@@ -675,24 +678,12 @@ linuxdvb_ddci_read_thread ( void *arg )
       }
       ddci_rd_thread->lddci_recv_pkgCntS += scrambled;
 
-      /* FIXME: split the received packets according to the PID in different
-       *        buffers and deliver them
-       * FIXME: How to determine the right service pointer?
-       */
-      /* as a first step we send the data to the associated service */
-      t = ddci_thread->lddci->t;
-      if (t) {
-        pthread_mutex_lock(&t->s_stream_mutex);
-        if (t->s_status == SERVICE_RUNNING) {
-          ts_recv_packet2((mpegts_service_t *)t, tsb, len);
-          ddci_rd_thread->lddci_recv_pkgCntW += num_pkg;
-        }
-        pthread_mutex_unlock(&t->s_stream_mutex);
-        clr_stat = 1;
-      } else if (clr_stat) {
-        clr_stat = 0;
+      mpegts_input_postdemux(ddci_thread->lddci->lddci_mi,
+                             ddci_thread->lddci->lddci_mm, tsb, len);
+
+      ddci_rd_thread->lddci_recv_pkgCntW += num_pkg;
 
-        /* in case of MCD/MTD this needs to be re-thinked */
+      if (idnode_set_empty(ddci_thread->lddci->lddci_services)) {
         linuxdvb_ddci_rd_thread_statistic(ddci_rd_thread);
         linuxdvb_ddci_rd_thread_statistic_clr(ddci_rd_thread);
       }
@@ -758,6 +749,7 @@ linuxdvb_ddci_create ( linuxdvb_transport_t *lcat, const char *ci_path)
   lddci->lddci_fdR = -1;
   linuxdvb_ddci_wr_thread_init(lddci);
   linuxdvb_ddci_rd_thread_init(lddci);
+  lddci->lddci_services = idnode_set_create(0);
 
   tvhtrace(LS_DDCI, "created %s %s", lddci->lddci_id, lddci->lddci_path);
 
@@ -771,6 +763,7 @@ linuxdvb_ddci_destroy ( linuxdvb_ddci_t *lddci )
     return;
   tvhtrace(LS_DDCI, "destroy %s %s", lddci->lddci_id, lddci->lddci_path);
   linuxdvb_ddci_close(lddci);
+  idnode_set_free(lddci->lddci_services);
   free(lddci->lddci_path);
   free(lddci);
 }
@@ -840,51 +833,56 @@ linuxdvb_ddci_put ( linuxdvb_ddci_t *lddci, const uint8_t *tsb, int len )
   linuxdvb_ddci_wr_thread_buffer_put(&lddci->lddci_wr_thread, tsb, len );
 }
 
-int
+void
 linuxdvb_ddci_assign ( linuxdvb_ddci_t *lddci, service_t *t )
 {
-  int ret = 0;
+  if (!idnode_set_exists(lddci->lddci_services, &t->s_id)) {
+    mpegts_service_t *s = (mpegts_service_t *)t;
+    const char *txt = "";
 
-  if (lddci->t && t != NULL) {
-    tvhwarn(LS_DDCI, "active assignment at %s changed to %p",
-            lddci->lddci_id, t );
-    ret = 1;
-  }
-  else if (t)
-    tvhnotice(LS_DDCI, "CAM %s assigned to %p", lddci->lddci_id, t );
-  else if (lddci->t) {
-    tvhnotice(LS_DDCI, "CAM %s unassigned from %p", lddci->lddci_id, lddci->t );
+    /* first service? -> store common data (for MCD all services have to
+     * have the same MUX/Input */
+    if (lddci->lddci_services->is_count == 0) {
+      lddci->lddci_mm = s->s_dvb_mux;
+      lddci->lddci_mi = s->s_dvb_active_input;
+    } else {
+      txt = "(MCD) ";
+      assert( lddci->lddci_mm == s->s_dvb_mux);
+      assert( lddci->lddci_mi == s->s_dvb_active_input);
+    }
 
-    /* in case of MCD/MTD this needs to be re-thinked */
-    linuxdvb_ddci_wr_thread_statistic_clr(&lddci->lddci_wr_thread);
-  }
+    tvhnotice(LS_DDCI, "CAM %s %sassigned to %p", lddci->lddci_id, txt, t );
 
-  lddci->t = t;
-  return ret;
+    idnode_set_add(lddci->lddci_services, &t->s_id, NULL, NULL);
+  }
 }
 
-int
-linuxdvb_ddci_is_assigned ( linuxdvb_ddci_t *lddci )
+void
+linuxdvb_ddci_unassign ( linuxdvb_ddci_t *lddci, service_t *t )
 {
-  return !!lddci->t;
+  if (idnode_set_exists(lddci->lddci_services, &t->s_id)) {
+    tvhnotice(LS_DDCI, "CAM %s unassigned from %p", lddci->lddci_id, t );
+
+    idnode_set_remove(lddci->lddci_services, &t->s_id);
+  }
+
+  if (lddci->lddci_services->is_count == 0) {
+    lddci->lddci_mm = NULL;
+    lddci->lddci_mi = NULL;
+    linuxdvb_ddci_wr_thread_statistic_clr(&lddci->lddci_wr_thread);
+  }
 }
 
 int
-linuxdvb_ddci_require_descramble
-  ( service_t *t, int_fast16_t pid, elementary_stream_t *st )
+linuxdvb_ddci_do_not_assign ( linuxdvb_ddci_t *lddci, service_t *t, int multi )
 {
-  int ret = 0;
+  mpegts_service_t *s = (mpegts_service_t *)t;
 
-  switch (pid) {
-    case DVB_CAT_PID:
-    case DVB_EIT_PID:
-      ++ret;
-      break;
-  }
+  /* nothing assigned? */
+  if (!lddci->lddci_mm) return 0;
 
-  /* DD CI requires all CA descriptor PIDs */
-  if (st && st->es_type == SCT_CA)
-    ++ret;
+  /* CAM can do multi channel decoding and new service uses the same mux? */
+  if (multi && (lddci->lddci_mm == s->s_dvb_mux)) return 0;
 
-  return ret;
+  return 1;
 }
index 3bb239260b782cf7845c686eb005c1729480aa0e..10d700e35c6b3cfbbf368f284a9b19e3669def02 100644 (file)
@@ -461,27 +461,13 @@ void
 linuxdvb_ddci_close ( linuxdvb_ddci_t *lddci );
 void
 linuxdvb_ddci_put ( linuxdvb_ddci_t *lddci, const uint8_t *tsb, int len );
-/* Un/Assign the service to DD CI CAM.
- * If t is NULL, the service is unassigned.
- *
- *  ret: 0 .. un/assigned
- *       1 .. assigned, but it was already assigned to another service
- */
-int
+void
 linuxdvb_ddci_assign ( linuxdvb_ddci_t *lddci, service_t *t );
+void
+linuxdvb_ddci_unassign ( linuxdvb_ddci_t *lddci, service_t *t );
+/* return 0, if ddci can be assigned to the given service */
 int
-linuxdvb_ddci_is_assigned ( linuxdvb_ddci_t *lddci );
-/* Checks if the given PID needs to be sent to the CAM (descrambler).
- * This will check for special PIDs only. Scrambled packets (scrambled bits set)
- * data needs to be forwarded in any case to the CAM.
- *
- *  ret:  0 .. not required
- *       >0 .. PID is required by the CAM
- */
-int
-linuxdvb_ddci_require_descramble
-  ( service_t *t, int_fast16_t pid, elementary_stream_t *st );
-
+linuxdvb_ddci_do_not_assign ( linuxdvb_ddci_t *lddci, service_t *t, int multi );
 #endif
 
 /*