mpegts: update to the way init scan table completion is handled

Should be a bit better at handling tables that may or may not exist.
We have an initial timeout after which we check if data for any tables
has been received but incomplete.

This is still far from ideal, really what is needed is to make this
all more async based on when we sync etc... but this will do for now.
This commit is contained in:
Adam Sutton 2013-12-21 22:06:15 +00:00
parent 70bf35b6f6
commit 13864f9eac
16 changed files with 165 additions and 94 deletions

View file

@ -264,7 +264,8 @@ struct mpegts_mux
* Scanning
*/
gtimer_t mm_initial_scan_timeout; // TODO: really? here?
int mm_initial_scan_init;
gtimer_t mm_initial_scan_timeout;
TAILQ_ENTRY(mpegts_mux) mm_initial_scan_link;
enum {
MM_SCAN_DONE, // All done
@ -559,7 +560,7 @@ mpegts_mux_t *mpegts_mux_create0
#define mpegts_mux_delete_by_uuid(u)\
{ mpegts_mux_t *mm = mpegts_mux_find(u); if (mm) mm->mm_delete(mm); }
void mpegts_mux_initial_scan_done ( mpegts_mux_t *mm );
void mpegts_mux_initial_scan_done ( mpegts_mux_t *mm, int log );
void mpegts_mux_initial_scan_fail ( mpegts_mux_t *mm );
void mpegts_mux_delete ( mpegts_mux_t *mm );

View file

@ -27,8 +27,8 @@
#define __TVH_DVB_SUPPORT_H__
struct mpegts_table;
/* Defaults */
struct mpegts_table_state;
struct mpegts_mux;
/* PIDs */
@ -100,7 +100,6 @@ struct mpegts_table;
int dvb_servicetype_lookup ( int t );
/* String Extraction */
typedef struct dvb_string_conv
@ -159,13 +158,8 @@ do {\
DVB_LOOP_INIT(ptr, len, off, lptr, llen);\
DVB_DESC_EACH(lptr, llen, dtag, dlen, dptr)\
/* PSI descriptors */
/* PSI table callbacks */
struct mpegts_table_state;
int dvb_table_end
(struct mpegts_table *mt, struct mpegts_table_state *st, int sect );
int dvb_table_begin
@ -190,6 +184,11 @@ int dvb_tdt_callback
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 );
/*
* Delivery systems and DVB API wrappers
*

View file

@ -476,7 +476,7 @@ dvb_table_complete
total++;
tvhtrace(mt->mt_name, "incomplete %d complete %d total %d",
mt->mt_incomplete, mt->mt_complete, total);
return -1;
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);
@ -499,7 +499,7 @@ dvb_table_end
rem = 0;
for (sa = 0; sa < 8; sa++)
rem |= st->sections[sa];
if (rem) return -1;
if (rem) return 1;
tvhtrace(mt->mt_name, " tableid %02X extraid %016" PRIx64 " completed",
st->tableid, st->extraid);
st->complete = 1;
@ -507,7 +507,7 @@ dvb_table_end
return dvb_table_complete(mt);
}
}
return -1;
return 2;
}
/*
@ -1588,3 +1588,45 @@ psi_parse_pmt
}
return ret;
}
/*
* Install default table sets
*/
void
psi_tables_default ( mpegts_mux_t *mm )
{
mpegts_table_add(mm, DVB_PAT_BASE, DVB_PAT_MASK, dvb_pat_callback,
NULL, "pat", MT_QUICKREQ | MT_CRC | MT_RECORD,
DVB_PAT_PID);
mpegts_table_add(mm, DVB_CAT_BASE, DVB_CAT_MASK, dvb_cat_callback,
NULL, "cat", MT_QUICKREQ | MT_CRC, DVB_CAT_PID);
}
void
psi_tables_dvb ( mpegts_mux_t *mm )
{
mpegts_table_add(mm, DVB_NIT_BASE, DVB_NIT_MASK, dvb_nit_callback,
NULL, "nit", MT_QUICKREQ | MT_CRC, DVB_NIT_PID);
mpegts_table_add(mm, DVB_SDT_BASE, DVB_SDT_MASK, dvb_sdt_callback,
NULL, "sdt", MT_QUICKREQ | MT_CRC | MT_RECORD,
DVB_SDT_PID);
mpegts_table_add(mm, DVB_BAT_BASE, DVB_BAT_MASK, dvb_bat_callback,
NULL, "bat", MT_CRC, DVB_BAT_PID);
}
void
psi_tables_atsc_c ( mpegts_mux_t *mm )
{
mpegts_table_add(mm, DVB_VCT_C_BASE, DVB_VCT_MASK, atsc_vct_callback,
NULL, "vct", MT_QUICKREQ | MT_CRC | MT_RECORD,
DVB_VCT_PID);
}
void
psi_tables_atsc_t ( mpegts_mux_t *mm )
{
mpegts_table_add(mm, DVB_VCT_T_BASE, DVB_VCT_MASK, atsc_vct_callback,
NULL, "vct", MT_QUICKREQ | MT_CRC | MT_RECORD,
DVB_VCT_PID);
}

View file

@ -346,14 +346,13 @@ iptv_input_mux_started ( iptv_mux_t *im )
}
/* Install table handlers */
// Note: we don't install NIT as we can't do mux discovery
// TODO: not currently installing ATSC handler
mpegts_table_add((mpegts_mux_t*)im, DVB_SDT_BASE, DVB_SDT_MASK,
dvb_sdt_callback, NULL, "sdt",
MT_QUICKREQ | MT_CRC | MT_RECORD, DVB_SDT_PID);
mpegts_table_add((mpegts_mux_t*)im, DVB_PAT_BASE, DVB_PAT_MASK,
dvb_pat_callback, NULL, "pat",
MT_QUICKREQ | MT_CRC | MT_RECORD, DVB_PAT_PID);
mpegts_mux_t *mm = (mpegts_mux_t*)im;
psi_tables_default(mm);
if (im->mm_iptv_atsc) {
psi_tables_atsc_t(mm);
psi_tables_atsc_c(mm);
} else
psi_tables_dvb(mm);
}
/* **************************************************************************

View file

@ -44,6 +44,12 @@ const idclass_t iptv_mux_class =
.name = "Interface",
.off = offsetof(iptv_mux_t, mm_iptv_interface),
},
{
.type = PT_BOOL,
.id = "iptv_atsc",
.name = "ATSC",
.off = offsetof(iptv_mux_t, mm_iptv_atsc),
},
{}
}
};

View file

@ -78,6 +78,8 @@ struct iptv_mux
char *mm_iptv_url;
char *mm_iptv_interface;
int mm_iptv_atsc;
uint8_t *mm_iptv_tsb;
int mm_iptv_pos;

View file

@ -404,41 +404,18 @@ linuxdvb_frontend_default_tables
{
mpegts_mux_t *mm = (mpegts_mux_t*)lm;
/* Common */
mpegts_table_add(mm, DVB_PAT_BASE, DVB_PAT_MASK, dvb_pat_callback,
NULL, "pat", MT_QUICKREQ | MT_CRC | MT_RECORD,
DVB_PAT_PID);
#if 0
mpegts_table_add(mm, DVB_CAT_BASE, DVB_CAT_MASK, dvb_cat_callback,
NULL, "cat", MT_CRC, DVB_CAT_PID);
#endif
psi_tables_default(mm);
/* ATSC */
if (lfe->lfe_info.type == FE_ATSC) {
int tableid;
if (lm->lm_tuning.dmc_fe_params.u.vsb.modulation == VSB_8)
tableid = DVB_VCT_T_BASE;
psi_tables_atsc_t(mm);
else
tableid = DVB_VCT_C_BASE;
mpegts_table_add(mm, tableid, DVB_VCT_MASK, atsc_vct_callback,
NULL, "vct", MT_QUICKREQ | MT_CRC | MT_RECORD,
DVB_VCT_PID);
psi_tables_atsc_c(mm);
/* DVB */
} else {
mpegts_table_add(mm, DVB_CAT_BASE, DVB_CAT_MASK, dvb_cat_callback,
NULL, "cat", MT_QUICKREQ | MT_CRC, DVB_CAT_PID);
mpegts_table_add(mm, DVB_NIT_BASE, DVB_NIT_MASK, dvb_nit_callback,
NULL, "nit", MT_QUICKREQ | MT_CRC, DVB_NIT_PID);
mpegts_table_add(mm, DVB_SDT_BASE, DVB_SDT_MASK, dvb_sdt_callback,
NULL, "sdt", MT_QUICKREQ | MT_CRC | MT_RECORD,
DVB_SDT_PID);
mpegts_table_add(mm, DVB_BAT_BASE, DVB_BAT_MASK, dvb_bat_callback,
NULL, "bat", MT_CRC, DVB_BAT_PID);
#if 0
mpegts_table_add(mm, DVB_TOT_BASE, DVB_TOT_MASK, dvb_tot_callback,
NULL, "tot", MT_CRC, DVB_TOT_PID);
#endif
psi_tables_dvb(mm);
}
}

View file

@ -73,19 +73,31 @@ mpegts_mux_instance_create0
}
static void
mpegts_mux_add_to_current ( mpegts_mux_t *mm, const char *buf )
mpegts_mux_add_to_current
( mpegts_mux_t *mm, const char *buf, mpegts_input_t *mi )
{
int t;
mpegts_network_t *mn = mm->mm_network;
/* Initial scanning */
if (mm->mm_initial_scan_status == MM_SCAN_PENDING) {
tvhtrace("mpegts", "%s - adding to current scan Q", buf);
TAILQ_REMOVE(&mn->mn_initial_scan_pending_queue, mm,
mm_initial_scan_link);
mm->mm_initial_scan_status = MM_SCAN_CURRENT;
mm->mm_initial_scan_status = MM_SCAN_CURRENT;
mm->mm_initial_scan_init = 0;
TAILQ_INSERT_TAIL(&mn->mn_initial_scan_current_queue, mm,
mm_initial_scan_link);
/* Get timeout */
t = 0;
if (mi && mi->mi_get_grace)
t = mi->mi_get_grace(mi, mm);
if (t < 5) t = 5; // lower bound
/* Setup timeout */
gtimer_arm(&mm->mm_initial_scan_timeout,
mpegts_mux_initial_scan_timeout, mm, 30);
mpegts_mux_initial_scan_timeout, mm, t);
}
}
@ -103,7 +115,7 @@ mpegts_mux_instance_start
if (mm->mm_active) {
*mmiptr = mm->mm_active;
tvhdebug("mpegts", "%s - already active", buf);
mpegts_mux_add_to_current(mm, buf);
mpegts_mux_add_to_current(mm, buf, mmi->mmi_input);
return 0;
}
@ -121,7 +133,7 @@ mpegts_mux_instance_start
mpegts_fire_event(mm, ml_mux_start);
/* Link */
mpegts_mux_add_to_current(mm, buf);
mpegts_mux_add_to_current(mm, buf, mmi->mmi_input);
return 0;
}
@ -223,7 +235,7 @@ mpegts_mux_class_initscan_notify ( void *p )
/* Stop */
} else {
if (mm->mm_initial_scan_status == MM_SCAN_CURRENT)
mpegts_mux_initial_scan_done(mm);
mpegts_mux_initial_scan_done(mm, 1);
else if (mm->mm_initial_scan_status == MM_SCAN_PENDING)
TAILQ_REMOVE(&mn->mn_initial_scan_pending_queue, mm,
mm_initial_scan_link);
@ -393,7 +405,7 @@ mpegts_mux_start
/* Already tuned */
if (mm->mm_active) {
tvhtrace("mpegts", "%s - already active", buf);
mpegts_mux_add_to_current(mm, buf);
mpegts_mux_add_to_current(mm, buf, mm->mm_active->mmi_input);
return 0;
}
@ -611,22 +623,75 @@ mpegts_mux_initial_scan_link ( mpegts_mux_t *mm )
static void
mpegts_mux_initial_scan_timeout ( void *aux )
{
int c, q;
char buf[256];
mpegts_mux_t *mm = aux;
mpegts_table_t *mt, *nxt;
mm->mm_display_name(mm, buf, sizeof(buf));
tvhinfo("mpegts", "%s - initial scan timed out", buf);
mpegts_mux_initial_scan_done(mm);
/* Timeout */
if (mm->mm_initial_scan_init) {
tvhinfo("mpegts", "%s - initial scan timed out", buf);
mpegts_mux_initial_scan_done(mm, 0);
return;
}
mm->mm_initial_scan_init = 1;
/* Check tables */
c = q = 0;
for (mt = LIST_FIRST(&mm->mm_tables); mt != NULL; mt = nxt) {
nxt = LIST_NEXT(mt, mt_link);
if (!(mt->mt_flags & MT_QUICKREQ)) continue;
if (!mt->mt_count) {
mpegts_table_destroy(mt);
} else if (!mt->mt_complete) {
q++;
} else {
c++;
}
}
/* No DATA - give up now */
if (!c) {
tvhinfo("mpegts", "%s - initial scan no data, failed", buf);
mpegts_mux_initial_scan_done(mm, 0);
/* Pending tables (another 20s - bit arbitrary) */
} else if (q) {
gtimer_arm(&mm->mm_initial_scan_timeout,
mpegts_mux_initial_scan_timeout, mm, 20);
return;
/* Complete */
} else {
mpegts_mux_initial_scan_done(mm, 1);
}
}
void
mpegts_mux_initial_scan_done ( mpegts_mux_t *mm )
mpegts_mux_initial_scan_done ( mpegts_mux_t *mm, int log )
{
char buf[256];
mpegts_network_t *mn = mm->mm_network;
mpegts_table_t *mt;
/* Log */
if (log) {
mm->mm_display_name(mm, buf, sizeof(buf));
tvhinfo("mpegts", "%s - initial scan complete", buf);
}
LIST_FOREACH(mt, &mm->mm_tables, mt_link) {
if (mt->mt_flags & MT_QUICKREQ) {
const char *s = "not found";
if (mt->mt_complete)
s = "complete";
else if (mt->mt_count)
s = "incomplete";
tvhinfo("mpegts", "%s - %s %s", buf, mt->mt_name, s);
}
}
/* Stop */
mm->mm_display_name(mm, buf, sizeof(buf));
tvhinfo("mpegts", "%s - initial scan complete", buf);
gtimer_disarm(&mm->mm_initial_scan_timeout);
assert(mm->mm_initial_scan_status == MM_SCAN_CURRENT);
mn->mn_initial_scan_num--;

View file

@ -226,7 +226,6 @@ mpegts_network_delete
/* Check */
assert(TAILQ_FIRST(&mn->mn_initial_scan_pending_queue) == NULL);
assert(TAILQ_FIRST(&mn->mn_initial_scan_current_queue) == NULL);
/* Disable timer */
gtimer_disarm(&mn->mn_initial_scan_timer);

View file

@ -34,14 +34,10 @@ mpegts_table_fastswitch ( mpegts_mux_t *mm )
return;
}
// TODO:
//dvb_mux_save(dm);
tvhlog(LOG_DEBUG, "mpegts", "initial scan for mm %p done", mm);
mpegts_mux_initial_scan_done(mm);
mpegts_mux_initial_scan_done(mm, 1);
}
void
mpegts_table_dispatch
( const uint8_t *sec, size_t r, void *aux )
@ -87,10 +83,10 @@ mpegts_table_dispatch
ret = mt->mt_callback(mt, sec+3, len, tid);
/* Good */
if(ret == 0)
if(ret >= 0)
mt->mt_count++;
if(mt->mt_flags & MT_QUICKREQ)
if(!ret && mt->mt_flags & MT_QUICKREQ)
mpegts_table_fastswitch(mt->mt_mux);
}

View file

@ -29,7 +29,7 @@ struct mpegts_network;
void tsfile_init ( int tuners );
/* Add a new file (multiplex) */
void tsfile_add_file ( const char *path, int atsc );
void tsfile_add_file ( const char *path );
#endif /* __TVH_TSFILE_H__ */

View file

@ -83,7 +83,7 @@ void tsfile_init ( int tuners )
/*
* Add multiplex
*/
void tsfile_add_file ( const char *path, int atsc )
void tsfile_add_file ( const char *path )
{
mpegts_input_t *mi;
mpegts_mux_t *mm;
@ -94,7 +94,7 @@ void tsfile_add_file ( const char *path, int atsc )
/* Create physical instance (for each tuner) */
LIST_FOREACH(mi, &tsfile_inputs, mi_global_link)
tsfile_mux_instance_create(path, mi, mm, atsc);
tsfile_mux_instance_create(path, mi, mm);
}
/******************************************************************************

View file

@ -214,21 +214,10 @@ tsfile_input_start_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *t )
mmi->mmi_mux->mm_active = t;
/* Install table handlers */
mpegts_table_add(mm, DVB_PAT_BASE, DVB_PAT_MASK, dvb_pat_callback,
NULL, "pat", MT_QUICKREQ | MT_CRC | MT_RECORD, DVB_PAT_PID);
if (!mmi->mmi_tsfile_atsc) {
mpegts_table_add(mm, DVB_SDT_BASE, DVB_SDT_MASK, dvb_sdt_callback,
NULL, "sdt", MT_QUICKREQ | MT_CRC | MT_RECORD, DVB_SDT_PID);
mpegts_table_add(mm, DVB_BAT_BASE, DVB_BAT_MASK, dvb_bat_callback,
NULL, "bat", MT_CRC, DVB_BAT_PID);
} else {
mpegts_table_add(mm, DVB_VCT_T_BASE, DVB_VCT_MASK, atsc_vct_callback,
NULL, "vct", MT_QUICKREQ | MT_CRC | MT_RECORD, DVB_VCT_PID);
mpegts_table_add(mm, DVB_VCT_C_BASE, DVB_VCT_MASK, atsc_vct_callback,
NULL, "vct", MT_QUICKREQ | MT_CRC | MT_RECORD, DVB_VCT_PID);
}
mpegts_table_add(mm, 0x1, 0xff, dvb_cat_callback, NULL, "cat",
MT_CRC, DVB_CAT_PID);
psi_tables_default(mm);
psi_tables_dvb(mm);
psi_tables_atsc_t(mm);
psi_tables_atsc_c(mm);
return 0;
}

View file

@ -24,7 +24,7 @@ extern const idclass_t mpegts_mux_instance_class;
tsfile_mux_instance_t *
tsfile_mux_instance_create
( const char *path, mpegts_input_t *mi, mpegts_mux_t *mm, int atsc )
( const char *path, mpegts_input_t *mi, mpegts_mux_t *mm )
{
#define tsfile_mux_instance_class mpegts_mux_instance_class
tsfile_mux_instance_t *mmi =
@ -32,7 +32,6 @@ tsfile_mux_instance_create
#undef tsfile_mux_instance_class
mmi->mmi_tsfile_path = strdup(path);
mmi->mmi_tsfile_pcr_pid = 0;
mmi->mmi_tsfile_atsc = atsc;
tvhtrace("tsfile", "mmi created %p path %s", mmi, mmi->mmi_tsfile_path);
return mmi;
}

View file

@ -50,7 +50,6 @@ struct tsfile_mux_instance
* File input
*/
int mmi_tsfile_atsc; ///< ATSC input
char *mmi_tsfile_path; ///< Source file path
th_pipe_t mmi_tsfile_pipe; ///< Thread control pipe
uint16_t mmi_tsfile_pcr_pid; ///< Timing control
@ -62,7 +61,7 @@ struct tsfile_mux_instance
mpegts_input_t *tsfile_input_create ( int idx );
tsfile_mux_instance_t *tsfile_mux_instance_create
( const char *path, mpegts_input_t *mi, mpegts_mux_t *mm, int atsc );
( const char *path, mpegts_input_t *mi, mpegts_mux_t *mm );
mpegts_mux_t *
tsfile_mux_create ( mpegts_network_t *mn );

View file

@ -437,8 +437,7 @@ main(int argc, char **argv)
opt_fileline = 0,
opt_threadid = 0,
opt_ipv6 = 0,
opt_tsfile_tuner = 0,
opt_tsfile_atsc = 0;
opt_tsfile_tuner = 0;
const char *opt_config = NULL,
*opt_user = NULL,
*opt_group = NULL,
@ -506,7 +505,6 @@ main(int argc, char **argv)
{ 0, NULL, "TODO: testing", OPT_BOOL, NULL },
{ 0, "tsfile_tuners", "Number of tsfile tuners", OPT_INT, &opt_tsfile_tuner },
{ 0, "tsfile", "tsfile input (mux file)", OPT_STR_LIST, &opt_tsfile },
{ 0, "tsfile_atsc", "tsfile input is ATSC", OPT_BOOL, &opt_tsfile_atsc }
};
@ -729,7 +727,7 @@ main(int argc, char **argv)
if(opt_tsfile.num) {
tsfile_init(opt_tsfile_tuner ?: opt_tsfile.num);
for (i = 0; i < opt_tsfile.num; i++)
tsfile_add_file(opt_tsfile.str[i], opt_tsfile_atsc);
tsfile_add_file(opt_tsfile.str[i]);
}
#endif
#if ENABLE_IPTV