From: Jasmin Jessich Date: Sun, 18 Feb 2018 02:47:22 +0000 (+0100) Subject: Add support for adding multiple services to DD CI X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=da50b461f31d1b66d06c78e1c4707efa35a14b65;p=thirdparty%2Ftvheadend.git Add support for adding multiple services to DD CI 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 --- diff --git a/src/descrambler/dvbcam.c b/src/descrambler/dvbcam.c index 0bba68e02..53d02634e 100644 --- a/src/descrambler/dvbcam.c +++ b/src/descrambler/dvbcam.c @@ -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; diff --git a/src/input/mpegts/linuxdvb/linuxdvb_ddci.c b/src/input/mpegts/linuxdvb/linuxdvb_ddci.c index f1cefb612..712f49935 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_ddci.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_ddci.c @@ -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; } diff --git a/src/input/mpegts/linuxdvb/linuxdvb_private.h b/src/input/mpegts/linuxdvb/linuxdvb_private.h index 3bb239260..10d700e35 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_private.h +++ b/src/input/mpegts/linuxdvb/linuxdvb_private.h @@ -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 /*