From 97e9c725f0b91d4b3c23ecaf1433b29343ac9ec8 Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Wed, 4 Sep 2013 01:04:54 +0100 Subject: [PATCH] mpegts: improvements to DVB SI processing I've made the table extraid 64 bits, as some entries require 32+X bits so a 32-bit field wasn't enough. Added callback for registering destruction (for dealloc'ing memory alloc'd for opaque). Added method of registering desciptor tag handlers, saves duplicating BAT processing used for OpenTV, which uses 1 custom descriptor. Improved the table completion detection and reduced level of debug that could swamp tvhlog queue. --- src/input/mpegts.h | 10 ++++-- src/input/mpegts/dvb.h | 2 +- src/input/mpegts/dvb_psi.c | 63 ++++++++++++++++++--------------- src/input/mpegts/mpegts_mux.c | 2 -- src/input/mpegts/mpegts_table.c | 2 ++ 5 files changed, 46 insertions(+), 33 deletions(-) diff --git a/src/input/mpegts.h b/src/input/mpegts.h index ddbcff57..cb71fb66 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -78,11 +78,11 @@ struct mpegts_psi_section typedef struct mpegts_table_state { int tableid; - int extraid; + uint64_t extraid; int version; int complete; uint32_t sections[8]; - RB_ENTRY(mpegts_table_state) link; + RB_ENTRY(mpegts_table_state) link; } mpegts_table_state_t; struct mpegts_table @@ -119,6 +119,8 @@ struct mpegts_table mpegts_table_callback_t mt_callback; RB_HEAD(,mpegts_table_state) mt_state; + int mt_complete; + int mt_incomplete; int mt_count; @@ -137,6 +139,10 @@ struct mpegts_table mpegts_psi_section_t mt_sect; struct mpegts_table_mux_cb *mt_mux_cb; + + void (*mt_destroy) (mpegts_table_t *mt); // Allow customisable destroy hook + // useful for dynamic allocation of + // the opaque field }; /** diff --git a/src/input/mpegts/dvb.h b/src/input/mpegts/dvb.h index 78d70137..721f1b62 100644 --- a/src/input/mpegts/dvb.h +++ b/src/input/mpegts/dvb.h @@ -160,7 +160,7 @@ int dvb_table_end (struct mpegts_table *mt, struct mpegts_table_state *st, int sect ); int dvb_table_begin (struct mpegts_table *mt, const uint8_t *ptr, int len, - int tableid, int extraid, int minlen, + int tableid, uint64_t extraid, int minlen, struct mpegts_table_state **st, int *sect, int *last, int *ver); int dvb_pat_callback diff --git a/src/input/mpegts/dvb_psi.c b/src/input/mpegts/dvb_psi.c index 3c93e62d..44c2a680 100644 --- a/src/input/mpegts/dvb_psi.c +++ b/src/input/mpegts/dvb_psi.c @@ -389,16 +389,24 @@ dvb_desc_local_channel static int sect_cmp ( struct mpegts_table_state *a, struct mpegts_table_state *b ) { - if (b->tableid != a->tableid) + if (a->tableid != b->tableid) return a->tableid - b->tableid; - return a->extraid - b->extraid; + if (a->extraid < b->extraid) + return -1; + if (a->extraid > b->extraid) + return 1; + return 0; } static void mpegts_table_state_reset - ( mpegts_table_state_t *st, int last ) + ( mpegts_table_t *mt, mpegts_table_state_t *st, int last ) { int i; + if (st->complete == 2) { + mt->mt_complete--; + mt->mt_incomplete++; + } st->complete = 0; memset(st->sections, 0, sizeof(st->sections)); for (i = 0; i < last / 32; i++) @@ -408,7 +416,7 @@ mpegts_table_state_reset static struct mpegts_table_state * mpegts_table_state_find - ( mpegts_table_t *mt, int tableid, int extraid, int last ) + ( mpegts_table_t *mt, int tableid, uint64_t extraid, int last ) { static struct mpegts_table_state *st, *skel = NULL; @@ -421,7 +429,8 @@ mpegts_table_state_find if (!st) { st = skel; skel = NULL; - mpegts_table_state_reset(st, last); + mt->mt_incomplete++; + mpegts_table_state_reset(mt, st, last); } return st; } @@ -433,19 +442,16 @@ static int dvb_table_complete (mpegts_table_t *mt) { - int c = 0, p = 0; - struct mpegts_table_state *st; - tvhtrace(mt->mt_name, "status: "); - RB_FOREACH(st, &mt->mt_state, link) { - tvhtrace(mt->mt_name, " tableid %02X extraid %08X ver %2d complete %d", - st->tableid, st->extraid, st->version, st->complete); - if (!st->complete) - p = 1; - else - c = MAX(c, st->complete); + if (mt->mt_incomplete || !mt->mt_complete) { + int total = 0; + mpegts_table_state_t *st; + RB_FOREACH(st, &mt->mt_state, link) + total++; + tvhtrace(mt->mt_name, "incomplete %d complete %d total %d", + mt->mt_incomplete, mt->mt_complete, total); + return -1; } - if (p || c != 2) return -1; - tvhdebug(mt->mt_name, "completed"); + tvhdebug(mt->mt_name, "subtable completed"); return 0; } @@ -456,6 +462,7 @@ dvb_table_end int sa, sb; uint32_t rem; if (st) { + assert(sect >= 0 && sect <= 255); sa = sect / 32; sb = sect % 32; st->sections[sa] &= ~(0x1 << (31 - sb)); @@ -464,9 +471,10 @@ dvb_table_end for (sa = 0; sa < 8; sa++) rem |= st->sections[sa]; if (rem) return -1; - tvhtrace(mt->mt_name, " tableid %02X extraid %08X completed", + tvhtrace(mt->mt_name, " tableid %02X extraid %016lX completed", st->tableid, st->extraid); st->complete = 1; + mt->mt_incomplete--; return dvb_table_complete(mt); } } @@ -479,7 +487,7 @@ dvb_table_end int dvb_table_begin (mpegts_table_t *mt, const uint8_t *ptr, int len, - int tableid, int extraid, int minlen, + int tableid, uint64_t extraid, int minlen, mpegts_table_state_t **ret, int *sect, int *last, int *ver) { mpegts_table_state_t *st; @@ -495,8 +503,8 @@ dvb_table_begin if((ptr[2] & 1) == 0) return -1; - tvhtrace(mt->mt_name, "tableid %02X extraid %08X len %d", - tableid, extraid, len); + tvhtrace(mt->mt_name, "pid %02X tableid %02X extraid %016lX len %d", + mt->mt_pid, tableid, extraid, len); /* Section info */ if (sect && ret) { @@ -510,7 +518,7 @@ dvb_table_begin if (st->complete && st->version != *ver) { tvhtrace(mt->mt_name, " new version, restart"); - mpegts_table_state_reset(st, *last); + mpegts_table_state_reset(mt, st, *last); } st->version = *ver; @@ -519,6 +527,7 @@ dvb_table_begin tvhtrace(mt->mt_name, " skip, already complete"); if (st->complete == 1) { st->complete = 2; + mt->mt_complete++; return dvb_table_complete(mt); } return -1; @@ -735,7 +744,7 @@ dvb_nit_callback /* Network Descriptors */ *name = 0; DVB_DESC_FOREACH(ptr, len, 5, lptr, llen, dtag, dlen, dptr) { - tvhdebug(mt->mt_name, " dtag %02X dlen %d", dtag, dlen); + tvhtrace(mt->mt_name, " dtag %02X dlen %d", dtag, dlen); switch (dtag) { case DVB_DESC_BOUQUET_NAME: @@ -773,7 +782,7 @@ dvb_nit_callback break; DVB_DESC_FOREACH(lptr, llen, 4, dlptr, dllen, dtag, dlen, dptr) { - tvhdebug(mt->mt_name, " dtag %02X dlen %d", dtag, dlen); + tvhtrace(mt->mt_name, " dtag %02X dlen %d", dtag, dlen); /* User-defined */ if (mt->mt_mux_cb) { @@ -882,9 +891,7 @@ dvb_sdt_callback int free_ca_mode = (ptr[3] >> 4) & 0x1; int stype = 0; char sprov[256], sname[256], sauth[256]; -#if ENABLE_TRACE int running_status = (ptr[3] >> 5) & 0x7; -#endif *sprov = *sname = *sauth = 0; tvhdebug("sdt", " sid %04X (%d) running %d free_ca %d", service_id, service_id, running_status, free_ca_mode); @@ -897,7 +904,7 @@ dvb_sdt_callback /* Descriptor loop */ DVB_DESC_EACH(lptr, llen, dtag, dlen, dptr) { - tvhdebug("sdt", " dtag %02X dlen %d", dtag, dlen); + tvhtrace("sdt", " dtag %02X dlen %d", dtag, dlen); switch (dtag) { case DVB_DESC_SERVICE: if (dvb_desc_service(dptr, dlen, &stype, sprov, @@ -911,7 +918,7 @@ dvb_sdt_callback } } - tvhdebug("sdt", " type %d name [%s] provider [%s] def_auth [%s]", + tvhtrace("sdt", " type %d name [%s] provider [%s] def_auth [%s]", stype, sname, sprov, sauth); if (!s) continue; diff --git a/src/input/mpegts/mpegts_mux.c b/src/input/mpegts/mpegts_mux.c index 93dd874a..dbb1baa8 100644 --- a/src/input/mpegts/mpegts_mux.c +++ b/src/input/mpegts/mpegts_mux.c @@ -371,8 +371,6 @@ mpegts_mux_start return SM_CODE_NO_FREE_ADAPTER; } - mpegts_fire_event(mm, ml_mux_start); - return 0; } diff --git a/src/input/mpegts/mpegts_table.c b/src/input/mpegts/mpegts_table.c index 3a46b011..74b7966c 100644 --- a/src/input/mpegts/mpegts_table.c +++ b/src/input/mpegts/mpegts_table.c @@ -115,6 +115,8 @@ mpegts_table_destroy ( mpegts_table_t *mt ) RB_REMOVE(&mt->mt_state, st, link); free(st); } + if (mt->mt_destroy) + mt->mt_destroy(mt); mpegts_table_release(mt); }