diff --git a/Makefile b/Makefile index fb454925..9dac791a 100644 --- a/Makefile +++ b/Makefile @@ -225,13 +225,15 @@ SRCS += src/muxer.c \ # Optional code # -# MPEGTS core +# MPEGTS core, order by usage (psi lib, tsdemux) SRCS-$(CONFIG_MPEGTS) += \ src/descrambler/descrambler.c \ src/descrambler/caclient.c \ src/input/mpegts.c \ src/input/mpegts/mpegts_pid.c \ src/input/mpegts/mpegts_input.c \ + src/input/mpegts/tsdemux.c \ + src/input/mpegts/dvb_psi_lib.c \ src/input/mpegts/mpegts_network.c \ src/input/mpegts/mpegts_mux.c \ src/input/mpegts/mpegts_service.c \ @@ -240,9 +242,8 @@ SRCS-$(CONFIG_MPEGTS) += \ src/input/mpegts/dvb_charset.c \ src/input/mpegts/dvb_psi.c \ src/input/mpegts/fastscan.c \ - src/input/mpegts/tsdemux.c \ src/input/mpegts/mpegts_mux_sched.c \ - src/input/mpegts/mpegts_network_scan.c \ + src/input/mpegts/mpegts_network_scan.c # MPEGTS DVB SRCS-${CONFIG_MPEGTS_DVB} += \ diff --git a/src/input/mpegts.h b/src/input/mpegts.h index 8d17964e..3708c06f 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -32,7 +32,6 @@ #define MPEGTS_ONID_NONE 0xFFFF #define MPEGTS_TSID_NONE 0xFFFF -#define MPEGTS_PSI_SECTION_SIZE 5000 #define MPEGTS_FULLMUX_PID 0x2000 #define MPEGTS_TABLES_PID 0x2001 #define MPEGTS_PID_NONE 0xFFFF @@ -119,9 +118,6 @@ struct mpegts_packet typedef int (*mpegts_table_callback_t) ( mpegts_table_t*, const uint8_t *buf, int len, int tableid ); -typedef void (*mpegts_psi_section_callback_t) - ( const uint8_t *tsb, size_t len, void *opaque ); - struct mpegts_table_mux_cb { int tag; @@ -129,13 +125,6 @@ struct mpegts_table_mux_cb const uint8_t dtag, const uint8_t *dptr, int dlen ); }; -struct mpegts_psi_section -{ - int ps_offset; - int ps_lock; - uint8_t ps_data[MPEGTS_PSI_SECTION_SIZE]; -}; - typedef struct mpegts_table_state { int tableid; @@ -267,13 +256,6 @@ struct mpegts_table_feed { uint8_t mtf_tsb[0]; }; -/* - * Assemble SI section - */ -void mpegts_psi_section_reassemble - ( mpegts_psi_section_t *ps, const uint8_t *tsb, int crc, int ccerr, - mpegts_psi_section_callback_t cb, void *opaque ); - /* ************************************************************************** * Logical network * *************************************************************************/ @@ -963,6 +945,33 @@ void mpegts_table_destroy ( mpegts_table_t *mt ); void mpegts_table_consistency_check( mpegts_mux_t *mm ); +void dvb_bat_destroy + (struct mpegts_table *mt); + +int dvb_pat_callback + (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid); +int dvb_cat_callback + (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid); +int dvb_pmt_callback + (struct mpegts_table *mt, const uint8_t *ptr, int len, int tabelid); +int dvb_nit_callback + (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid); +int dvb_bat_callback + (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid); +int dvb_fs_sdt_callback + (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid); +int dvb_sdt_callback + (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid); +int dvb_tdt_callback + (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid); +int atsc_vct_callback + (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid); + +void psi_tables_default ( struct mpegts_mux *mm ); +void psi_tables_dvb ( struct mpegts_mux *mm ); +void psi_tables_atsc_t ( struct mpegts_mux *mm ); +void psi_tables_atsc_c ( struct mpegts_mux *mm ); + mpegts_service_t *mpegts_service_create0 ( mpegts_service_t *ms, const idclass_t *class, const char *uuid, mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid, htsmsg_t *conf ); diff --git a/src/input/mpegts/dvb.h b/src/input/mpegts/dvb.h index 034200ac..8a749246 100644 --- a/src/input/mpegts/dvb.h +++ b/src/input/mpegts/dvb.h @@ -199,6 +199,29 @@ do {\ DVB_LOOP_INIT(ptr, len, off, lptr, llen);\ DVB_DESC_EACH(lptr, llen, dtag, dlen, dptr)\ +/* + * SI typedefs + */ + +#define MPEGTS_PSI_SECTION_SIZE 5000 + +typedef struct mpegts_psi_section +{ + int ps_offset; + int ps_lock; + uint8_t ps_data[MPEGTS_PSI_SECTION_SIZE]; +} mpegts_psi_section_t; + +typedef void (*mpegts_psi_section_callback_t) + ( const uint8_t *tsb, size_t len, void *opaque ); + +/* + * Assemble SI section + */ +void mpegts_psi_section_reassemble + ( mpegts_psi_section_t *ps, const uint8_t *tsb, int crc, int ccerr, + mpegts_psi_section_callback_t cb, void *opaque ); + /* PSI table callbacks */ int dvb_table_end @@ -209,32 +232,6 @@ int dvb_table_begin struct mpegts_table_state **st, int *sect, int *last, int *ver); void dvb_table_reset (struct mpegts_table *mt); -void dvb_bat_destroy - (struct mpegts_table *mt); - -int dvb_pat_callback - (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid); -int dvb_cat_callback - (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid); -int dvb_pmt_callback - (struct mpegts_table *mt, const uint8_t *ptr, int len, int tabelid); -int dvb_nit_callback - (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid); -int dvb_bat_callback - (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid); -int dvb_fs_sdt_callback - (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid); -int dvb_sdt_callback - (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid); -int dvb_tdt_callback - (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid); -int atsc_vct_callback - (struct mpegts_table *mt, const uint8_t *ptr, int len, int tableid); - -void psi_tables_default ( struct mpegts_mux *mm ); -void psi_tables_dvb ( struct mpegts_mux *mm ); -void psi_tables_atsc_t ( struct mpegts_mux *mm ); -void psi_tables_atsc_c ( struct mpegts_mux *mm ); extern htsmsg_t *satellites; diff --git a/src/input/mpegts/dvb_psi.c b/src/input/mpegts/dvb_psi.c index 7f4fa584..beba4a72 100644 --- a/src/input/mpegts/dvb_psi.c +++ b/src/input/mpegts/dvb_psi.c @@ -1,6 +1,6 @@ /* * MPEG TS Program Specific Information code - * Copyright (C) 2007 - 2010 Andreas �man + * Copyright (C) 2007 - 2010 Andreas Öman * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -81,44 +81,11 @@ typedef struct dvb_bat { LIST_HEAD(,dvb_bat_id) bats; } dvb_bat_t; -SKEL_DECLARE(mpegts_table_state_skel, struct mpegts_table_state); - int dvb_bouquets_parse = 1; static int psi_parse_pmt(mpegts_mux_t *mux, mpegts_service_t *t, const uint8_t *ptr, int len); -/* ************************************************************************** - * Lookup tables - * *************************************************************************/ - -static const int dvb_servicetype_map[][2] = { - { 0x01, ST_SDTV }, /* SDTV (MPEG2) */ - { 0x02, ST_RADIO }, - { 0x11, ST_HDTV }, /* HDTV (MPEG2) */ - { 0x16, ST_SDTV }, /* Advanced codec SDTV */ - { 0x19, ST_HDTV }, /* Advanced codec HDTV */ - { 0x80, ST_SDTV }, /* NET POA - Cabo SDTV */ - { 0x91, ST_HDTV }, /* Bell TV HDTV */ - { 0x96, ST_SDTV }, /* Bell TV SDTV */ - { 0xA0, ST_HDTV }, /* Bell TV tiered HDTV */ - { 0xA4, ST_HDTV }, /* DN HDTV */ - { 0xA6, ST_HDTV }, /* Bell TV tiered HDTV */ - { 0xA8, ST_SDTV }, /* DN advanced SDTV */ - { 0xD3, ST_SDTV }, /* SKY TV SDTV */ -}; - -int -dvb_servicetype_lookup ( int t ) -{ - int i; - for (i = 0; i < ARRAY_SIZE(dvb_servicetype_map); i++) { - if (dvb_servicetype_map[i][0] == t) - return dvb_servicetype_map[i][1]; - } - return -1; -} - static inline int mpegts_mux_alive(mpegts_mux_t *mm) { @@ -871,199 +838,6 @@ dvb_bskyb_local_channels #endif /* ENABLE_MPEGTS_DVB */ -/* ************************************************************************** - * Tables - * *************************************************************************/ - -static int sect_cmp - ( struct mpegts_table_state *a, struct mpegts_table_state *b ) -{ - if (a->tableid != b->tableid) - return a->tableid - b->tableid; - if (a->extraid < b->extraid) - return -1; - if (a->extraid > b->extraid) - return 1; - return 0; -} - -static void -mpegts_table_state_reset - ( mpegts_table_t *mt, mpegts_table_state_t *st, int last ) -{ - int i; - mt->mt_finished = 0; - st->complete = 0; - st->version = 0xff; /* invalid */ - memset(st->sections, 0, sizeof(st->sections)); - for (i = 0; i < last / 32; i++) - st->sections[i] = 0xFFFFFFFF; - st->sections[last / 32] = 0xFFFFFFFF << (31 - (last % 32)); -} - -static struct mpegts_table_state * -mpegts_table_state_find - ( mpegts_table_t *mt, int tableid, uint64_t extraid, int last ) -{ - struct mpegts_table_state *st; - - /* Find state */ - SKEL_ALLOC(mpegts_table_state_skel); - mpegts_table_state_skel->tableid = tableid; - mpegts_table_state_skel->extraid = extraid; - st = RB_INSERT_SORTED(&mt->mt_state, mpegts_table_state_skel, link, sect_cmp); - if (!st) { - st = mpegts_table_state_skel; - SKEL_USED(mpegts_table_state_skel); - mt->mt_incomplete++; - mpegts_table_state_reset(mt, st, last); - } - return st; -} - -/* - * End table - */ -static int -dvb_table_complete - (mpegts_table_t *mt) -{ - 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 2; - } - if (!mt->mt_finished) - tvhdebug(mt->mt_name, "completed pid %d table %08X / %08x", mt->mt_pid, mt->mt_table, mt->mt_mask); - mt->mt_finished = 1; - return 0; -} - -int -dvb_table_end - (mpegts_table_t *mt, mpegts_table_state_t *st, int sect) -{ - int sa, sb; - uint32_t rem; - if (st && !st->complete) { - assert(sect >= 0 && sect <= 255); - sa = sect / 32; - sb = sect % 32; - st->sections[sa] &= ~(0x1 << (31 - sb)); - if (!st->sections[sa]) { - rem = 0; - for (sa = 0; sa < 8; sa++) - rem |= st->sections[sa]; - if (rem) return 1; - tvhtrace(mt->mt_name, " tableid %02X extraid %016" PRIx64 " completed", - st->tableid, st->extraid); - st->complete = 1; - mt->mt_incomplete--; - return dvb_table_complete(mt); - } - } else if (st) - return dvb_table_complete(mt); - return 2; -} - -/* - * Begin table - */ -int -dvb_table_begin - (mpegts_table_t *mt, const uint8_t *ptr, int len, - int tableid, uint64_t extraid, int minlen, - mpegts_table_state_t **ret, int *sect, int *last, int *ver) -{ - mpegts_table_state_t *st; - uint32_t sa, sb; - - /* Not long enough */ - if (len < minlen) { - tvhdebug(mt->mt_name, "invalid table length %d min %d", len, minlen); - return -1; - } - - /* Ignore next */ - if((ptr[2] & 1) == 0) - return -1; - - tvhtrace(mt->mt_name, "pid %02X tableid %02X extraid %016" PRIx64 " len %d", - mt->mt_pid, tableid, extraid, len); - - /* Section info */ - if (sect && ret) { - *sect = ptr[3]; - *last = ptr[4]; - *ver = (ptr[2] >> 1) & 0x1F; - *ret = st = mpegts_table_state_find(mt, tableid, extraid, *last); - tvhtrace(mt->mt_name, " section %d last %d ver %d (ver %d st %d incomp %d comp %d)", - *sect, *last, *ver, st->version, st->complete, mt->mt_incomplete, mt->mt_complete); - - /* Ignore previous version */ - /* This check is for the broken PMT tables where: - * last 0 version 21 = PCR + Audio PID 0x0044 - * last 0 version 22 = Audio PID 0x0044, PCR + Video PID 0x0045 - */ - if (*last == 0 && st->version - 1 == *ver) - return -1; - - /* New version */ - if (st->version != *ver) { - if (st->complete == 2) - mt->mt_complete--; - if (st->complete) - mt->mt_incomplete++; - tvhtrace(mt->mt_name, " new version, restart"); - mpegts_table_state_reset(mt, st, *last); - st->version = *ver; - } - - /* Complete? */ - if (st->complete) { - tvhtrace(mt->mt_name, " skip, already complete (%i)", st->complete); - if (st->complete == 1) { - st->complete = 2; - mt->mt_complete++; - return dvb_table_complete(mt); - } else if (st->complete == 2) { - return dvb_table_complete(mt); - } - assert(0); - } - - /* Already seen? */ - sa = *sect / 32; - sb = *sect % 32; - if (!(st->sections[sa] & (0x1 << (31 - sb)))) { - tvhtrace(mt->mt_name, " skip, already seen"); - return -1; - } - } - - tvhlog_hexdump(mt->mt_name, ptr, len); - - return 1; -} - -void -dvb_table_reset(mpegts_table_t *mt) -{ - mpegts_table_state_t *st; - - tvhtrace(mt->mt_name, "pid %02X complete reset", mt->mt_pid); - mt->mt_incomplete = 0; - mt->mt_complete = 0; - while ((st = RB_FIRST(&mt->mt_state)) != NULL) { - RB_REMOVE(&mt->mt_state, st, link); - free(st); - } -} - /* * PAT processing */ diff --git a/src/input/mpegts/dvb_psi_lib.c b/src/input/mpegts/dvb_psi_lib.c new file mode 100644 index 00000000..49604969 --- /dev/null +++ b/src/input/mpegts/dvb_psi_lib.c @@ -0,0 +1,340 @@ +/* + * MPEG TS Program Specific Information Library code + * Copyright (C) 2007 - 2010 Andreas Öman + * Copyright (C) 2015 Jaroslav Kysela + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "tvheadend.h" +#include "input.h" +#include "dvb.h" + +SKEL_DECLARE(mpegts_table_state_skel, struct mpegts_table_state); + +/* ************************************************************************** + * Lookup tables + * *************************************************************************/ + +static const int dvb_servicetype_map[][2] = { + { 0x01, ST_SDTV }, /* SDTV (MPEG2) */ + { 0x02, ST_RADIO }, + { 0x11, ST_HDTV }, /* HDTV (MPEG2) */ + { 0x16, ST_SDTV }, /* Advanced codec SDTV */ + { 0x19, ST_HDTV }, /* Advanced codec HDTV */ + { 0x80, ST_SDTV }, /* NET POA - Cabo SDTV */ + { 0x91, ST_HDTV }, /* Bell TV HDTV */ + { 0x96, ST_SDTV }, /* Bell TV SDTV */ + { 0xA0, ST_HDTV }, /* Bell TV tiered HDTV */ + { 0xA4, ST_HDTV }, /* DN HDTV */ + { 0xA6, ST_HDTV }, /* Bell TV tiered HDTV */ + { 0xA8, ST_SDTV }, /* DN advanced SDTV */ + { 0xD3, ST_SDTV }, /* SKY TV SDTV */ +}; + +int +dvb_servicetype_lookup ( int t ) +{ + int i; + for (i = 0; i < ARRAY_SIZE(dvb_servicetype_map); i++) { + if (dvb_servicetype_map[i][0] == t) + return dvb_servicetype_map[i][1]; + } + return -1; +} + +/* ************************************************************************** + * Tables + * *************************************************************************/ + +/* + * Section assembly + */ +static int +mpegts_psi_section_reassemble0 + ( mpegts_psi_section_t *ps, const uint8_t *data, + int len, int start, int crc, + mpegts_psi_section_callback_t cb, void *opaque) +{ + int excess, tsize; + + if(start) { + // Payload unit start indicator + ps->ps_offset = 0; + ps->ps_lock = 1; + } + + if(!ps->ps_lock) + return -1; + + memcpy(ps->ps_data + ps->ps_offset, data, len); + ps->ps_offset += len; + + if(ps->ps_offset < 3) { + /* We don't know the total length yet */ + return len; + } + + tsize = 3 + (((ps->ps_data[1] & 0xf) << 8) | ps->ps_data[2]); + + if(ps->ps_offset < tsize) + return len; // Not there yet + + excess = ps->ps_offset - tsize; + + if(crc && tvh_crc32(ps->ps_data, tsize, 0xffffffff)) + return -1; + + ps->ps_offset = 0; + if (cb) + cb(ps->ps_data, tsize - (crc ? 4 : 0), opaque); + return len - excess; +} + +/** + * + */ +void +mpegts_psi_section_reassemble + (mpegts_psi_section_t *ps, const uint8_t *tsb, int crc, int ccerr, + mpegts_psi_section_callback_t cb, void *opaque) +{ + int off = tsb[3] & 0x20 ? tsb[4] + 5 : 4; + int pusi = tsb[1] & 0x40; + int r; + + if (ccerr) + ps->ps_lock = 0; + + if(off >= 188) { + ps->ps_lock = 0; + return; + } + + if(pusi) { + int len = tsb[off++]; + if(len > 0) { + if(len > 188 - off) { + ps->ps_lock = 0; + return; + } + mpegts_psi_section_reassemble0(ps, tsb + off, len, 0, crc, cb, opaque); + off += len; + } + } + + while(off < 188) { + r = mpegts_psi_section_reassemble0(ps, tsb + off, 188 - off, pusi, crc, + cb, opaque); + if(r < 0) { + ps->ps_lock = 0; + break; + } + off += r; + pusi = 0; + } +} + +/* + * + */ + +static int sect_cmp + ( struct mpegts_table_state *a, struct mpegts_table_state *b ) +{ + if (a->tableid != b->tableid) + return a->tableid - b->tableid; + if (a->extraid < b->extraid) + return -1; + if (a->extraid > b->extraid) + return 1; + return 0; +} + +static void +mpegts_table_state_reset + ( mpegts_table_t *mt, mpegts_table_state_t *st, int last ) +{ + int i; + mt->mt_finished = 0; + st->complete = 0; + st->version = 0xff; /* invalid */ + memset(st->sections, 0, sizeof(st->sections)); + for (i = 0; i < last / 32; i++) + st->sections[i] = 0xFFFFFFFF; + st->sections[last / 32] = 0xFFFFFFFF << (31 - (last % 32)); +} + +static struct mpegts_table_state * +mpegts_table_state_find + ( mpegts_table_t *mt, int tableid, uint64_t extraid, int last ) +{ + struct mpegts_table_state *st; + + /* Find state */ + SKEL_ALLOC(mpegts_table_state_skel); + mpegts_table_state_skel->tableid = tableid; + mpegts_table_state_skel->extraid = extraid; + st = RB_INSERT_SORTED(&mt->mt_state, mpegts_table_state_skel, link, sect_cmp); + if (!st) { + st = mpegts_table_state_skel; + SKEL_USED(mpegts_table_state_skel); + mt->mt_incomplete++; + mpegts_table_state_reset(mt, st, last); + } + return st; +} + +/* + * End table + */ +static int +dvb_table_complete + (mpegts_table_t *mt) +{ + 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 2; + } + if (!mt->mt_finished) + tvhdebug(mt->mt_name, "completed pid %d table %08X / %08x", mt->mt_pid, mt->mt_table, mt->mt_mask); + mt->mt_finished = 1; + return 0; +} + +int +dvb_table_end + (mpegts_table_t *mt, mpegts_table_state_t *st, int sect) +{ + int sa, sb; + uint32_t rem; + if (st && !st->complete) { + assert(sect >= 0 && sect <= 255); + sa = sect / 32; + sb = sect % 32; + st->sections[sa] &= ~(0x1 << (31 - sb)); + if (!st->sections[sa]) { + rem = 0; + for (sa = 0; sa < 8; sa++) + rem |= st->sections[sa]; + if (rem) return 1; + tvhtrace(mt->mt_name, " tableid %02X extraid %016" PRIx64 " completed", + st->tableid, st->extraid); + st->complete = 1; + mt->mt_incomplete--; + return dvb_table_complete(mt); + } + } else if (st) + return dvb_table_complete(mt); + return 2; +} + +/* + * Begin table + */ +int +dvb_table_begin + (mpegts_table_t *mt, const uint8_t *ptr, int len, + int tableid, uint64_t extraid, int minlen, + mpegts_table_state_t **ret, int *sect, int *last, int *ver) +{ + mpegts_table_state_t *st; + uint32_t sa, sb; + + /* Not long enough */ + if (len < minlen) { + tvhdebug(mt->mt_name, "invalid table length %d min %d", len, minlen); + return -1; + } + + /* Ignore next */ + if((ptr[2] & 1) == 0) + return -1; + + tvhtrace(mt->mt_name, "pid %02X tableid %02X extraid %016" PRIx64 " len %d", + mt->mt_pid, tableid, extraid, len); + + /* Section info */ + if (sect && ret) { + *sect = ptr[3]; + *last = ptr[4]; + *ver = (ptr[2] >> 1) & 0x1F; + *ret = st = mpegts_table_state_find(mt, tableid, extraid, *last); + tvhtrace(mt->mt_name, " section %d last %d ver %d (ver %d st %d incomp %d comp %d)", + *sect, *last, *ver, st->version, st->complete, mt->mt_incomplete, mt->mt_complete); + + /* Ignore previous version */ + /* This check is for the broken PMT tables where: + * last 0 version 21 = PCR + Audio PID 0x0044 + * last 0 version 22 = Audio PID 0x0044, PCR + Video PID 0x0045 + */ + if (*last == 0 && st->version - 1 == *ver) + return -1; + + /* New version */ + if (st->version != *ver) { + if (st->complete == 2) + mt->mt_complete--; + if (st->complete) + mt->mt_incomplete++; + tvhtrace(mt->mt_name, " new version, restart"); + mpegts_table_state_reset(mt, st, *last); + st->version = *ver; + } + + /* Complete? */ + if (st->complete) { + tvhtrace(mt->mt_name, " skip, already complete (%i)", st->complete); + if (st->complete == 1) { + st->complete = 2; + mt->mt_complete++; + return dvb_table_complete(mt); + } else if (st->complete == 2) { + return dvb_table_complete(mt); + } + assert(0); + } + + /* Already seen? */ + sa = *sect / 32; + sb = *sect % 32; + if (!(st->sections[sa] & (0x1 << (31 - sb)))) { + tvhtrace(mt->mt_name, " skip, already seen"); + return -1; + } + } + + tvhlog_hexdump(mt->mt_name, ptr, len); + + return 1; +} + +void +dvb_table_reset(mpegts_table_t *mt) +{ + mpegts_table_state_t *st; + + tvhtrace(mt->mt_name, "pid %02X complete reset", mt->mt_pid); + mt->mt_incomplete = 0; + mt->mt_complete = 0; + while ((st = RB_FIRST(&mt->mt_state)) != NULL) { + RB_REMOVE(&mt->mt_state, st, link); + free(st); + } +} diff --git a/src/input/mpegts/mpegts_table.c b/src/input/mpegts/mpegts_table.c index 2dfb8bb0..f27b671f 100644 --- a/src/input/mpegts/mpegts_table.c +++ b/src/input/mpegts/mpegts_table.c @@ -295,96 +295,6 @@ mpegts_table_flush_all ( mpegts_mux_t *mm ) pthread_mutex_unlock(&mm->mm_tables_lock); } -/* - * Section assembly - */ -static int -mpegts_psi_section_reassemble0 - ( mpegts_psi_section_t *ps, const uint8_t *data, - int len, int start, int crc, - mpegts_psi_section_callback_t cb, void *opaque) -{ - int excess, tsize; - - if(start) { - // Payload unit start indicator - ps->ps_offset = 0; - ps->ps_lock = 1; - } - - if(!ps->ps_lock) - return -1; - - memcpy(ps->ps_data + ps->ps_offset, data, len); - ps->ps_offset += len; - - if(ps->ps_offset < 3) { - /* We don't know the total length yet */ - return len; - } - - tsize = 3 + (((ps->ps_data[1] & 0xf) << 8) | ps->ps_data[2]); - - if(ps->ps_offset < tsize) - return len; // Not there yet - - excess = ps->ps_offset - tsize; - - if(crc && tvh_crc32(ps->ps_data, tsize, 0xffffffff)) - return -1; - - ps->ps_offset = 0; - if (cb) - cb(ps->ps_data, tsize - (crc ? 4 : 0), opaque); - return len - excess; -} - - -/** - * - */ -void -mpegts_psi_section_reassemble - (mpegts_psi_section_t *ps, const uint8_t *tsb, int crc, int ccerr, - mpegts_psi_section_callback_t cb, void *opaque) -{ - int off = tsb[3] & 0x20 ? tsb[4] + 5 : 4; - int pusi = tsb[1] & 0x40; - int r; - - if (ccerr) - ps->ps_lock = 0; - - if(off >= 188) { - ps->ps_lock = 0; - return; - } - - if(pusi) { - int len = tsb[off++]; - if(len > 0) { - if(len > 188 - off) { - ps->ps_lock = 0; - return; - } - mpegts_psi_section_reassemble0(ps, tsb + off, len, 0, crc, cb, opaque); - off += len; - } - } - - while(off < 188) { - r = mpegts_psi_section_reassemble0(ps, tsb + off, 188 - off, pusi, crc, - cb, opaque); - if(r < 0) { - ps->ps_lock = 0; - break; - } - off += r; - pusi = 0; - } -} - - /****************************************************************************** * Editor Configuration