From 69ac1e378d94579b37079f948bca96e8cadd3c9f Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Wed, 11 Jun 2014 00:31:02 +0100 Subject: [PATCH] mpegts: add service and mux cleaning code --- src/input/mpegts.h | 14 ++++++++ src/input/mpegts/dvb_psi.c | 19 +++++++++-- src/input/mpegts/mpegts_mux.c | 54 +++++++++++++++++++++++++++++-- src/input/mpegts/mpegts_network.c | 32 ++++++++++++------ src/input/mpegts/mpegts_service.c | 19 ++++++++++- 5 files changed, 124 insertions(+), 14 deletions(-) diff --git a/src/input/mpegts.h b/src/input/mpegts.h index cf899a82..4c91caa0 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -298,6 +298,8 @@ struct mpegts_network char *mn_charset; int mn_idlescan; int mn_ignore_chnum; + int mn_autoclean_svc; + int mn_autoclean_mux; }; typedef enum mpegts_mux_scan_state @@ -343,6 +345,12 @@ struct mpegts_mux uint16_t mm_onid; uint16_t mm_tsid; + /* + * Versioning + */ + int64_t mm_created; + int64_t mm_updated; + /* * Services */ @@ -445,6 +453,12 @@ struct mpegts_service int s_dvb_prefcapid_lock; uint16_t s_dvb_forcecaid; + /* + * History + */ + int64_t s_dvb_created; + int64_t s_dvb_updated; + /* * EIT/EPG control */ diff --git a/src/input/mpegts/dvb_psi.c b/src/input/mpegts/dvb_psi.c index 817b0b74..ab0045da 100644 --- a/src/input/mpegts/dvb_psi.c +++ b/src/input/mpegts/dvb_psi.c @@ -1011,6 +1011,7 @@ dvb_pat_callback /* Multiplex */ tvhdebug("pat", "tsid %04X (%d)", tsid, tsid); mpegts_mux_set_tsid(mm, tsid, 1); + mm->mm_updated = dispatch_clock; /* Process each programme */ ptr += 5; @@ -1031,6 +1032,7 @@ dvb_pat_callback tvhdebug("pat", " sid %04X (%d) on pid %04X (%d)", sid, sid, pid, pid); int save = 0; if ((s = mpegts_service_find(mm, sid, pid, 1, &save))) { + s->s_dvb_updated = dispatch_clock; mpegts_table_add(mm, DVB_PMT_BASE, DVB_PMT_MASK, dvb_pmt_callback, NULL, "pmt", MT_CRC | MT_QUICKREQ | MT_SCANSUBS, pid); @@ -1121,11 +1123,13 @@ dvb_pmt_callback sid = ptr[0] << 8 | ptr[1]; r = dvb_table_begin(mt, ptr, len, tableid, sid, 9, &st, §, &last, &ver); if (r != 1) return r; + mm->mm_updated = dispatch_clock; /* Find service */ LIST_FOREACH(s, &mm->mm_services, s_dvb_mux_link) if (s->s_dvb_service_id == sid) break; if (!s) return -1; + s->s_dvb_updated = dispatch_clock; /* Process */ tvhdebug("pmt", "sid %04X (%d)", sid, sid); @@ -1486,6 +1490,10 @@ dvb_nit_callback #endif break; } + + /* Update */ + if (mux) + mm->mm_updated = dispatch_clock; } } @@ -1528,8 +1536,9 @@ dvb_sdt_callback LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link) if (mm->mm_onid == onid && mm->mm_tsid == tsid) break; - goto done; + if (!mm) goto done; } + mm->mm_updated = dispatch_clock; /* Service loop */ len -= 8; @@ -1554,6 +1563,9 @@ dvb_sdt_callback s = mpegts_service_find(mm, service_id, 0, 1, &save); charset = dvb_charset_find(mn, mm, s); + /* Update time and version */ + s->s_dvb_updated = dispatch_clock; + /* Descriptor loop */ DVB_DESC_EACH(lptr, llen, dtag, dlen, dptr) { tvhtrace("sdt", " dtag %02X dlen %d", dtag, dlen); @@ -1645,7 +1657,8 @@ dvb_sdt_callback /* Done */ done: - return dvb_table_end(mt, st, sect); + r = dvb_table_end(mt, st, sect); + return r; } /* @@ -1677,6 +1690,7 @@ atsc_vct_callback &st, §, &last, &ver); if (r != 1) return r; tvhdebug("vct", "tsid %04X (%d)", tsid, tsid); + mm->mm_updated = dispatch_clock; /* # channels */ count = ptr[6]; @@ -1713,6 +1727,7 @@ atsc_vct_callback /* Find the service */ if (!(s = mpegts_service_find(mm, sid, 0, 1, &save))) goto next; + s->s_dvb_updated = dispatch_clock; /* Update */ if (strcmp(s->s_dvb_svcname ?: "", chname)) { diff --git a/src/input/mpegts/mpegts_mux.c b/src/input/mpegts/mpegts_mux.c index dbb17f0c..89733ecc 100644 --- a/src/input/mpegts/mpegts_mux.c +++ b/src/input/mpegts/mpegts_mux.c @@ -440,7 +440,23 @@ const idclass_t mpegts_mux_class = .off = offsetof(mpegts_mux_t, mm_pmt_06_ac3), .opts = PO_ADVANCED, }, - {} + { + .type = PT_S64, + .id = "created", + .name = "Created", + .off = offsetof(mpegts_mux_t, mm_created), + .opts = PO_ADVANCED | PO_RDONLY, + .istime = "%F %T", + }, + { + .type = PT_S64, + .id = "updated", + .name = "Updated", + .off = offsetof(mpegts_mux_t, mm_updated), + .opts = PO_ADVANCED | PO_RDONLY, + .istime = "%F %T", + }, + {}, } }; @@ -463,7 +479,10 @@ mpegts_mux_delete ( mpegts_mux_t *mm, int delconf ) char buf[256]; mpegts_mux_nice_name(mm, buf, sizeof(buf)); - tvhinfo("mpegts", "%s (%p) - deleting", buf, mm); + if (delconf) + tvhinfo("mpegts", "%s (%p) - deleting", buf, mm); + else + tvhtrace("mpegts", "%s (%p) - deleting", buf, mm); /* Stop */ mm->mm_stop(mm, 1); @@ -831,6 +850,21 @@ mpegts_mux_close_table ( mpegts_mux_t *mm, mpegts_table_t *mt ) * Scanning * *************************************************************************/ +#define MPEGTS_AUTOCLEAN_PERIOD (86400L * 7) // 1 week + +static void +mpegts_mux_clean_services ( const char *mname, mpegts_mux_t *mm ) +{ + mpegts_service_t *s, *n; + for (s = LIST_FIRST(&mm->mm_services); s != NULL; s = n) { + n = LIST_NEXT(s, s_dvb_mux_link); + if (dispatch_clock < (s->s_dvb_updated + MPEGTS_AUTOCLEAN_PERIOD)) + continue; + tvhinfo("mpegts", "%s - autoclean svc %s", mname, s->s_nicename); + service_destroy((service_t*)s, 1); + } +} + void mpegts_mux_scan_done ( mpegts_mux_t *mm, const char *buf, int res ) { @@ -853,6 +887,10 @@ mpegts_mux_scan_done ( mpegts_mux_t *mm, const char *buf, int res ) } pthread_mutex_unlock(&mm->mm_tables_lock); + /* Check for out of date services */ + if (mm->mm_network->mn_autoclean_svc) + mpegts_mux_clean_services(buf, mm); + if (res) mpegts_network_scan_mux_done(mm); else @@ -904,6 +942,15 @@ again: tvhinfo("mpegts", "%s - scan no data, failed", buf); mpegts_mux_scan_done(mm, buf, 0); + /* Mark disabled */ + if (mm->mm_network->mn_autoclean_mux) { + if (dispatch_clock > (mm->mm_updated + MPEGTS_AUTOCLEAN_PERIOD)) { + tvhinfo("mpegts", "%s - autoclean mux", buf); + mm->mm_delete(mm, 1); + return; + } + } + /* Pending tables (another 20s or 30s - bit arbitrary) */ } else if (q) { tvhinfo("mpegts", "%s - scan needs more time", buf); @@ -935,6 +982,9 @@ mpegts_mux_create0 return NULL; } + /* Set time */ + mm->mm_created = dispatch_clock; + /* Enabled by default */ mm->mm_enabled = 1; mm->mm_epg = 1; diff --git a/src/input/mpegts/mpegts_network.c b/src/input/mpegts/mpegts_network.c index 4a0ac58f..c15cd170 100644 --- a/src/input/mpegts/mpegts_network.c +++ b/src/input/mpegts/mpegts_network.c @@ -154,21 +154,14 @@ const idclass_t mpegts_network_class = { .type = PT_BOOL, .id = "autodiscovery", - .name = "Network Discovery", + .name = "Autodiscover Muxes", .off = offsetof(mpegts_network_t, mn_autodiscovery), .def.i = 1 }, - { - .type = PT_BOOL, - .id = "skipinitscan", - .name = "Skip Initial Scan", - .off = offsetof(mpegts_network_t, mn_skipinitscan), - .def.i = 1 - }, { .type = PT_BOOL, .id = "idlescan", - .name = "Idle Scan Muxes", + .name = "Autoscan Muxes", .off = offsetof(mpegts_network_t, mn_idlescan), .def.i = 0, .notify = mpegts_network_class_idlescan_notify, @@ -180,6 +173,27 @@ const idclass_t mpegts_network_class = .off = offsetof(mpegts_network_t, mn_ignore_chnum), .def.i = 0, }, + { + .type = PT_BOOL, + .id = "autoclean_svc`", + .name = "Autoclean Services", + .off = offsetof(mpegts_network_t, mn_autoclean_svc), + .def.i = 1, + }, + { + .type = PT_BOOL, + .id = "autoclean_mux", + .name = "Autoclean Muxes", + .off = offsetof(mpegts_network_t, mn_autoclean_mux), + .def.i = 1, + }, + { + .type = PT_BOOL, + .id = "skipinitscan", + .name = "Skip Initial Scan", + .off = offsetof(mpegts_network_t, mn_skipinitscan), + .def.i = 1 + }, { .type = PT_STR, .id = "charset", diff --git a/src/input/mpegts/mpegts_service.c b/src/input/mpegts/mpegts_service.c index 1d561e09..8831c84a 100644 --- a/src/input/mpegts/mpegts_service.c +++ b/src/input/mpegts/mpegts_service.c @@ -183,6 +183,22 @@ const idclass_t mpegts_service_class = .off = offsetof(mpegts_service_t, s_dvb_forcecaid), .opts = PO_ADVANCED | PO_HEXA, }, + { + .type = PT_S64, + .id = "created", + .name = "Created", + .off = offsetof(mpegts_service_t, s_dvb_created), + .opts = PO_ADVANCED | PO_RDONLY, + .istime = "%F %T", + }, + { + .type = PT_S64, + .id = "updated", + .name = "Updated", + .off = offsetof(mpegts_service_t, s_dvb_updated), + .opts = PO_ADVANCED | PO_RDONLY, + .istime = "%F %T", + }, {}, } }; @@ -514,7 +530,8 @@ mpegts_service_create0 if (service_create0((service_t*)s, class, uuid, S_MPEG_TS, conf) == NULL) return NULL; - + s->s_dvb_created = dispatch_clock; + /* Create */ sbuf_init(&s->s_tsbuf); if (!conf) {