diff --git a/src/input/mpegts.h b/src/input/mpegts.h index 5445c0f2..6f37f341 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -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 ); diff --git a/src/input/mpegts/dvb.h b/src/input/mpegts/dvb.h index 9320bc6d..d2d61ed1 100644 --- a/src/input/mpegts/dvb.h +++ b/src/input/mpegts/dvb.h @@ -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 * diff --git a/src/input/mpegts/dvb_psi.c b/src/input/mpegts/dvb_psi.c index 01845a26..4f9a6956 100644 --- a/src/input/mpegts/dvb_psi.c +++ b/src/input/mpegts/dvb_psi.c @@ -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); +} diff --git a/src/input/mpegts/iptv/iptv.c b/src/input/mpegts/iptv/iptv.c index 9e4375ab..5cdd9ec4 100644 --- a/src/input/mpegts/iptv/iptv.c +++ b/src/input/mpegts/iptv/iptv.c @@ -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); } /* ************************************************************************** diff --git a/src/input/mpegts/iptv/iptv_mux.c b/src/input/mpegts/iptv/iptv_mux.c index 9d4e38e6..5c7a603a 100644 --- a/src/input/mpegts/iptv/iptv_mux.c +++ b/src/input/mpegts/iptv/iptv_mux.c @@ -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), + }, {} } }; diff --git a/src/input/mpegts/iptv/iptv_private.h b/src/input/mpegts/iptv/iptv_private.h index c35d4a41..c0283ce9 100644 --- a/src/input/mpegts/iptv/iptv_private.h +++ b/src/input/mpegts/iptv/iptv_private.h @@ -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; diff --git a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c index 82fa1775..4d6d4e05 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c @@ -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); } } diff --git a/src/input/mpegts/mpegts_mux.c b/src/input/mpegts/mpegts_mux.c index 1a14441b..400866dd 100644 --- a/src/input/mpegts/mpegts_mux.c +++ b/src/input/mpegts/mpegts_mux.c @@ -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--; diff --git a/src/input/mpegts/mpegts_network.c b/src/input/mpegts/mpegts_network.c index 4ad2d8f4..f3bcc59f 100644 --- a/src/input/mpegts/mpegts_network.c +++ b/src/input/mpegts/mpegts_network.c @@ -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); diff --git a/src/input/mpegts/mpegts_table.c b/src/input/mpegts/mpegts_table.c index efa60f0b..4475771c 100644 --- a/src/input/mpegts/mpegts_table.c +++ b/src/input/mpegts/mpegts_table.c @@ -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); } diff --git a/src/input/mpegts/tsfile.h b/src/input/mpegts/tsfile.h index 54ec1ae9..6a9e0f7b 100644 --- a/src/input/mpegts/tsfile.h +++ b/src/input/mpegts/tsfile.h @@ -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__ */ diff --git a/src/input/mpegts/tsfile/tsfile.c b/src/input/mpegts/tsfile/tsfile.c index d35b472f..d05fe469 100644 --- a/src/input/mpegts/tsfile/tsfile.c +++ b/src/input/mpegts/tsfile/tsfile.c @@ -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); } /****************************************************************************** diff --git a/src/input/mpegts/tsfile/tsfile_input.c b/src/input/mpegts/tsfile/tsfile_input.c index 28c2bb57..bd6a09a5 100644 --- a/src/input/mpegts/tsfile/tsfile_input.c +++ b/src/input/mpegts/tsfile/tsfile_input.c @@ -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; } diff --git a/src/input/mpegts/tsfile/tsfile_mux.c b/src/input/mpegts/tsfile/tsfile_mux.c index 6256a96e..380175ea 100644 --- a/src/input/mpegts/tsfile/tsfile_mux.c +++ b/src/input/mpegts/tsfile/tsfile_mux.c @@ -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; } diff --git a/src/input/mpegts/tsfile/tsfile_private.h b/src/input/mpegts/tsfile/tsfile_private.h index 36a9d6e9..afb8c404 100644 --- a/src/input/mpegts/tsfile/tsfile_private.h +++ b/src/input/mpegts/tsfile/tsfile_private.h @@ -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 ); diff --git a/src/main.c b/src/main.c index 0f3d37c9..61a9025d 100644 --- a/src/main.c +++ b/src/main.c @@ -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