dt = calloc(1, sizeof(*dt));
TAILQ_INIT(&dt->sections);
dt->table = mpegts_table_add(mux, 0, 0, descrambler_table_callback,
- dt, "descrambler", MT_FULL | flags, pid);
+ dt, "descrambler",
+ MT_FULL | MT_DEFER | flags, pid);
if (dt->table)
dt->table->mt_service = (mpegts_service_t *)service;
TAILQ_INSERT_TAIL(&mux->mm_descrambler_tables, dt, link);
*/
int mt_flags;
-#define MT_CRC 0x01
-#define MT_FULL 0x02
-#define MT_QUICKREQ 0x04
-#define MT_RECORD 0x08
-#define MT_SKIPSUBS 0x10
-#define MT_SCANSUBS 0x20
-#define MT_FAST 0x40
-#define MT_SLOW 0x80
+#define MT_CRC 0x0001
+#define MT_FULL 0x0002
+#define MT_QUICKREQ 0x0004
+#define MT_RECORD 0x0008
+#define MT_SKIPSUBS 0x0010
+#define MT_SCANSUBS 0x0020
+#define MT_FAST 0x0040
+#define MT_SLOW 0x0080
+#define MT_DEFER 0x0100
/**
* Cycle queue
*/
LIST_ENTRY(mpegts_table) mt_link;
+ LIST_ENTRY(mpegts_table) mt_defer_link;
mpegts_mux_t *mt_mux;
char *mt_name;
RB_HEAD(,mpegts_table_state) mt_state;
int mt_complete;
int mt_incomplete;
- int mt_finished;
- int mt_subscribed;
+ uint8_t mt_finished;
+ uint8_t mt_subscribed;
+ uint8_t mt_defer_cmd;
+ uint8_t mt_defer_reg;
int mt_count;
int mm_num_tables;
LIST_HEAD(, mpegts_table) mm_tables;
+ LIST_HEAD(, mpegts_table) mm_defer_tables;
+ pthread_mutex_t mm_defer_tables_lock;
TAILQ_HEAD(, mpegts_table) mm_table_queue;
LIST_HEAD(, caid) mm_descrambler_caids;
}
}
+static void
+mpegts_input_table_waiting ( mpegts_input_t *mi, mpegts_mux_t *mm )
+{
+ mpegts_table_t *mt;
+ int type;
+
+ pthread_mutex_lock(&mm->mm_defer_tables_lock);
+ while ((mt = LIST_FIRST(&mm->mm_defer_tables)) != NULL) {
+ LIST_REMOVE(mt, mt_defer_link);
+ if (mt->mt_destroyed)
+ continue;
+ type = 0;
+ if (mt->mt_flags & MT_FAST) type |= MPS_FTABLE;
+ if (mt->mt_flags & MT_SLOW) type |= MPS_TABLE;
+ if (mt->mt_flags & MT_RECORD) type |= MPS_STREAM;
+ if ((type & (MPS_FTABLE | MPS_TABLE)) == 0) type |= MPS_TABLE;
+ if (mt->mt_defer_cmd == 1) {
+ mt->mt_defer_cmd = 0;
+ mt->mt_defer_reg = 1;
+ LIST_INSERT_HEAD(&mm->mm_tables, mt, mt_link);
+ mm->mm_num_tables++;
+ if (!mt->mt_subscribed) {
+ mt->mt_subscribed = 1;
+ pthread_mutex_unlock(&mm->mm_defer_tables_lock);
+ mi->mi_open_pid(mi, mm, mt->mt_pid, type, mt);
+ }
+ } else if (mt->mt_defer_cmd == 2) {
+ mt->mt_defer_cmd = 0;
+ mt->mt_defer_reg = 0;
+ LIST_REMOVE(mt, mt_link);
+ mm->mm_num_tables--;
+ if (mt->mt_subscribed) {
+ mt->mt_subscribed = 0;
+ pthread_mutex_unlock(&mm->mm_defer_tables_lock);
+ mi->mi_close_pid(mi, mm, mt->mt_pid, type, mt);
+ }
+ } else {
+ pthread_mutex_unlock(&mm->mm_defer_tables_lock);
+ }
+ mpegts_table_release(mt);
+ pthread_mutex_lock(&mm->mm_defer_tables_lock);
+ }
+ pthread_mutex_unlock(&mm->mm_defer_tables_lock);
+}
+
static void
mpegts_input_process
( mpegts_input_t *mi, mpegts_packet_t *mpkt )
/* Process */
pthread_mutex_lock(&mi->mi_output_lock);
- if (mp->mp_mux && mp->mp_mux->mm_active)
+ if (mp->mp_mux && mp->mp_mux->mm_active) {
+ mpegts_input_table_waiting(mi, mp->mp_mux);
mpegts_input_process(mi, mp);
+ }
pthread_mutex_unlock(&mi->mi_output_lock);
/* Cleanup */
mm->mm_num_tables++;
return;
}
+ if (mt->mt_flags & MT_DEFER) {
+ pthread_mutex_lock(&mm->mm_defer_tables_lock);
+ if (mt->mt_defer_reg || mt->mt_defer_cmd == 1) {
+ pthread_mutex_unlock(&mm->mm_defer_tables_lock);
+ return;
+ }
+ mpegts_table_grab(mt); /* thread will release the table */
+ mt->mt_defer_cmd = 1;
+ LIST_INSERT_HEAD(&mm->mm_defer_tables, mt, mt_defer_link);
+ pthread_mutex_unlock(&mm->mm_defer_tables_lock);
+ return;
+ }
mi = mm->mm_active->mmi_input;
pthread_mutex_lock(&mi->mi_output_lock);
LIST_INSERT_HEAD(&mm->mm_tables, mt, mt_link);
mm->mm_num_tables--;
return;
}
+ if (mt->mt_flags & MT_DEFER) {
+ pthread_mutex_lock(&mm->mm_defer_tables_lock);
+ if (mt->mt_defer_cmd == 2) {
+ pthread_mutex_unlock(&mm->mm_defer_tables_lock);
+ return;
+ }
+ if (mt->mt_defer_cmd == 1) {
+ LIST_REMOVE(mt, mt_defer_link);
+ mt->mt_defer_cmd = 0;
+ pthread_mutex_unlock(&mm->mm_defer_tables_lock);
+ mpegts_table_release(mt);
+ return;
+ }
+ if (!mt->mt_defer_reg) {
+ pthread_mutex_unlock(&mm->mm_defer_tables_lock);
+ return;
+ }
+ mpegts_table_grab(mt); /* thread will release the table */
+ mt->mt_defer_cmd = 2;
+ LIST_INSERT_HEAD(&mm->mm_defer_tables, mt, mt_defer_link);
+ pthread_mutex_unlock(&mm->mm_defer_tables_lock);
+ return;
+ }
mi = mm->mm_active->mmi_input;
pthread_mutex_lock(&mi->mi_output_lock);
LIST_REMOVE(mt, mt_link);
/* Table processing */
mm->mm_open_table = mpegts_mux_open_table;
mm->mm_close_table = mpegts_mux_close_table;
+ pthread_mutex_init(&mm->mm_defer_tables_lock, NULL);
TAILQ_INIT(&mm->mm_table_queue);
LIST_INIT(&mm->mm_descrambler_caids);
TAILQ_INIT(&mm->mm_descrambler_tables);
{
mpegts_table_t *mt;
descrambler_flush_tables(mm);
- while ((mt = LIST_FIRST(&mm->mm_tables)))
+ pthread_mutex_lock(&mm->mm_defer_tables_lock);
+ while ((mt = LIST_FIRST(&mm->mm_defer_tables))) {
+ LIST_REMOVE(mt, mt_defer_link);
+ mt->mt_defer_cmd = 0;
+ mpegts_table_release(mt);
+ }
+ pthread_mutex_unlock(&mm->mm_defer_tables_lock);
+ while ((mt = LIST_FIRST(&mm->mm_tables))) {
+ if ((mt->mt_flags & MT_DEFER) && mt->mt_defer_reg)
+ mt->mt_flags &= ~MT_DEFER; /* force destroy */
mpegts_table_destroy(mt);
+ }
}
/*