diff --git a/src/descrambler/descrambler.c b/src/descrambler/descrambler.c index 030efa4b..a3d44882 100755 --- a/src/descrambler/descrambler.c +++ b/src/descrambler/descrambler.c @@ -442,7 +442,8 @@ descrambler_open_pid_( mpegts_mux_t *mux, void *opaque, int pid, 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); diff --git a/src/input/mpegts.h b/src/input/mpegts.h index f4674faa..61bb2ba4 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -142,14 +142,15 @@ struct mpegts_table */ 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 @@ -164,6 +165,7 @@ struct mpegts_table */ LIST_ENTRY(mpegts_table) mt_link; + LIST_ENTRY(mpegts_table) mt_defer_link; mpegts_mux_t *mt_mux; char *mt_name; @@ -174,8 +176,10 @@ struct mpegts_table 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; @@ -371,6 +375,8 @@ struct mpegts_mux 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; diff --git a/src/input/mpegts/mpegts_input.c b/src/input/mpegts/mpegts_input.c index 77f75203..4ef4268f 100644 --- a/src/input/mpegts/mpegts_input.c +++ b/src/input/mpegts/mpegts_input.c @@ -576,6 +576,51 @@ mpegts_input_table_dispatch ( mpegts_mux_t *mm, const uint8_t *tsb ) } } +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 ) @@ -723,8 +768,10 @@ mpegts_input_thread ( void * p ) /* 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 */ diff --git a/src/input/mpegts/mpegts_mux.c b/src/input/mpegts/mpegts_mux.c index 1e1fa2bf..58094cee 100644 --- a/src/input/mpegts/mpegts_mux.c +++ b/src/input/mpegts/mpegts_mux.c @@ -720,6 +720,18 @@ mpegts_mux_open_table ( mpegts_mux_t *mm, mpegts_table_t *mt, int subscribe ) 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); @@ -747,6 +759,29 @@ mpegts_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt ) 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); @@ -876,6 +911,7 @@ mpegts_mux_create0 /* 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); diff --git a/src/input/mpegts/mpegts_table.c b/src/input/mpegts/mpegts_table.c index 6632b51e..5032a0de 100644 --- a/src/input/mpegts/mpegts_table.c +++ b/src/input/mpegts/mpegts_table.c @@ -197,8 +197,18 @@ mpegts_table_flush_all ( mpegts_mux_t *mm ) { 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); + } } /*