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;
};
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);
}
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);
}
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);
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);
}
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;
}
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
/*