diff --git a/src/dvb/dvb_tables.c b/src/dvb/dvb_tables.c index e01da23e..7f9d7172 100644 --- a/src/dvb/dvb_tables.c +++ b/src/dvb/dvb_tables.c @@ -667,6 +667,10 @@ dvb_sdt_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, free(t->tht_svcname); t->tht_svcname = strdup(chname); + + pthread_mutex_lock(&t->tht_stream_mutex); + transport_make_nicename(t); + pthread_mutex_unlock(&t->tht_stream_mutex); t->tht_config_save(t); } diff --git a/src/dvb/dvb_transport.c b/src/dvb/dvb_transport.c index d11725fd..345ec945 100644 --- a/src/dvb/dvb_transport.c +++ b/src/dvb/dvb_transport.c @@ -219,6 +219,7 @@ dvb_transport_load(th_dvb_mux_instance_t *tdmi) t->tht_svcname = s ? strdup(s) : NULL; pthread_mutex_lock(&t->tht_stream_mutex); + transport_make_nicename(t); psi_load_transport_settings(c, t); pthread_mutex_unlock(&t->tht_stream_mutex); @@ -366,6 +367,10 @@ dvb_transport_find(th_dvb_mux_instance_t *tdmi, uint16_t sid, int pmt_pid, LIST_INSERT_HEAD(&tdmi->tdmi_transports, t, tht_group_link); + pthread_mutex_lock(&t->tht_stream_mutex); + transport_make_nicename(t); + pthread_mutex_unlock(&t->tht_stream_mutex); + dvb_adapter_notify(tdmi->tdmi_adapter); return t; } diff --git a/src/iptv_input.c b/src/iptv_input.c index da0eaa10..bd359bf3 100644 --- a/src/iptv_input.c +++ b/src/iptv_input.c @@ -406,6 +406,10 @@ iptv_transport_find(const char *id, int create) LIST_INSERT_HEAD(&iptv_all_transports, t, tht_group_link); + pthread_mutex_lock(&t->tht_stream_mutex); + transport_make_nicename(t); + pthread_mutex_unlock(&t->tht_stream_mutex); + return t; } diff --git a/src/main.c b/src/main.c index 8e284a16..71df781e 100644 --- a/src/main.c +++ b/src/main.c @@ -562,3 +562,28 @@ scopedunlock(pthread_mutex_t **mtxp) { pthread_mutex_unlock(*mtxp); } + + +void +limitedlog(loglimiter_t *ll, const char *sys, const char *o, const char *event) +{ + time_t now; + char buf[64]; + time(&now); + + ll->events++; + if(ll->last == now) + return; // Duplicate event + + if(ll->last <= now - 10) { + // Too old, reset duplicate counter + ll->events = 0; + buf[0] = 0; + } else { + snprintf(buf, sizeof(buf), ", %d duplicate log lines suppressed", + ll->events); + } + + tvhlog(LOG_WARNING, sys, "%s: %s%s", o, event, buf); + ll->last = now; +} diff --git a/src/parsers.c b/src/parsers.c index 4939c3df..650048cd 100644 --- a/src/parsers.c +++ b/src/parsers.c @@ -533,18 +533,18 @@ parse_pes_header(th_transport_t *t, th_stream_t *st, uint8_t *buf, size_t len) hlen = getu8(buf, len); if(len < hlen || (hdr & 0xc0) != 0x80) - return -1; + goto err; if((flags & 0xc0) == 0xc0) { if(hlen < 10) - return -1; + goto err; pts = getpts(buf, len); dts = getpts(buf, len); } else if((flags & 0xc0) == 0x80) { if(hlen < 5) - return -1; + goto err; dts = pts = getpts(buf, len); } else @@ -553,6 +553,11 @@ parse_pes_header(th_transport_t *t, th_stream_t *st, uint8_t *buf, size_t len) st->st_curdts = dts & PTS_MASK; st->st_curpts = pts & PTS_MASK; return hlen + 3; + + err: + limitedlog(&st->st_loglimit_pes, "TS", transport_component_nicename(st), + "Corrupted PES header"); + return -1; } @@ -1056,7 +1061,6 @@ parser_deliver(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt, } } else { /* DTS wrapped, increase upper bits */ - printf("Wrap detected\n"); st->st_dts_epoch += PTS_MASK + 1; st->st_bad_dts = 0; } diff --git a/src/rawtsinput.c b/src/rawtsinput.c index f7119992..fbdc74f2 100644 --- a/src/rawtsinput.c +++ b/src/rawtsinput.c @@ -122,6 +122,10 @@ rawts_transport_add(rawts_t *rt, uint16_t sid, int pmt_pid) t->tht_svcname = strdup(tmp); + pthread_mutex_lock(&t->tht_stream_mutex); + transport_make_nicename(t); + pthread_mutex_unlock(&t->tht_stream_mutex); + tvhlog(LOG_NOTICE, "rawts", "Added service %d (pmt: %d)", sid, pmt_pid); LIST_INSERT_HEAD(&rt->rt_transports, t, tht_group_link); diff --git a/src/transports.c b/src/transports.c index e2fe5363..d3a139da 100644 --- a/src/transports.c +++ b/src/transports.c @@ -172,6 +172,7 @@ transport_stream_destroy(th_transport_t *t, th_stream_t *st) if(t->tht_status == TRANSPORT_RUNNING) stream_clean(st); LIST_REMOVE(st, st_link); + free(st->st_nicename); free(st); } @@ -469,6 +470,7 @@ transport_destroy(th_transport_t *t) while((st = LIST_FIRST(&t->tht_components)) != NULL) { LIST_REMOVE(st, st_link); + free(st->st_nicename); free(st); } @@ -522,6 +524,59 @@ transport_find_by_identifier(const char *identifier) } +/** + * + */ +static void +transport_stream_make_nicename(th_transport_t *t, th_stream_t *st) +{ + char buf[100]; + if(st->st_pid != -1) + snprintf(buf, sizeof(buf), "%s: %s @ #%d", + transport_nicename(t), + streaming_component_type2txt(st->st_type), st->st_pid); + else + snprintf(buf, sizeof(buf), "%s: %s", + transport_nicename(t), + streaming_component_type2txt(st->st_type)); + + free(st->st_nicename); + st->st_nicename = strdup(buf); +} + + +/** + * + */ +void +transport_make_nicename(th_transport_t *t) +{ + char buf[100]; + source_info_t si; + th_stream_t *st; + + lock_assert(&t->tht_stream_mutex); + + t->tht_setsourceinfo(t, &si); + + snprintf(buf, sizeof(buf), + "%s%s%s%s%s", + si.si_adapter ?: "", si.si_adapter ? "/" : "", + si.si_mux ?: "", si.si_mux ? "/" : "", + si.si_service ?: ""); + + transport_source_info_free(&si); + + free(t->tht_nicename); + t->tht_nicename = strdup(buf); + + printf("%s -> %s\n", t->tht_identifier, t->tht_nicename); + + + LIST_FOREACH(st, &t->tht_components, st_link) + transport_stream_make_nicename(t, st); +} + /** * Add a new stream to a transport @@ -543,13 +598,10 @@ transport_stream_create(th_transport_t *t, int pid, return st; } - if(t->tht_flags & THT_DEBUG) - tvhlog(LOG_DEBUG, "transport", "%s: Add stream \"%s\", pid: %d", - t->tht_identifier, streaming_component_type2txt(type), pid); - st = calloc(1, sizeof(th_stream_t)); st->st_index = idx + 1; st->st_type = type; + LIST_INSERT_HEAD(&t->tht_components, st, st_link); st->st_pid = pid; @@ -562,6 +614,11 @@ transport_stream_create(th_transport_t *t, int pid, avgstat_init(&st->st_rate, 10); avgstat_init(&st->st_cc_errors, 10); + transport_stream_make_nicename(t, st); + + if(t->tht_flags & THT_DEBUG) + tvhlog(LOG_DEBUG, "transport", "Add stream %s", st->st_nicename); + if(t->tht_status == TRANSPORT_RUNNING) stream_init(st); @@ -900,3 +957,19 @@ transport_source_info_copy(source_info_t *dst, source_info_t *src) COPY(service); #undef COPY } + + +/** + * + */ +const char * +transport_nicename(th_transport_t *t) +{ + return t->tht_nicename; +} + +const char * +transport_component_nicename(th_stream_t *st) +{ + return st->st_nicename; +} diff --git a/src/transports.h b/src/transports.h index 31987411..775ca922 100644 --- a/src/transports.h +++ b/src/transports.h @@ -91,4 +91,10 @@ void transport_source_info_free(source_info_t *si); void transport_source_info_copy(source_info_t *dst, source_info_t *src); +void transport_make_nicename(th_transport_t *t); + +const char *transport_nicename(th_transport_t *t); + +const char *transport_component_nicename(th_stream_t *st); + #endif /* TRANSPORTS_H */ diff --git a/src/tsdemux.c b/src/tsdemux.c index 4a5f863d..20e7c1b0 100644 --- a/src/tsdemux.c +++ b/src/tsdemux.c @@ -82,13 +82,8 @@ ts_recv_packet0(th_transport_t *t, th_stream_t *st, uint8_t *tsb) cc = tsb[3] & 0xf; if(st->st_cc_valid && cc != st->st_cc) { /* Incorrect CC */ - - tvhlog(LOG_DEBUG, "TS", - "Continuity counter error on %s : %s PID #%d (%s)", - t->tht_svcname ?: "???", - streaming_component_type2txt(st->st_type), - st->st_pid, t->tht_identifier); - + limitedlog(&st->st_loglimit_cc, "TS", transport_component_nicename(st), + "Continuity counter error"); avgstat_add(&t->tht_cc_errors, 1, dispatch_clock); avgstat_add(&st->st_cc_errors, 1, dispatch_clock); err = 1; @@ -211,9 +206,12 @@ ts_recv_packet1(th_transport_t *t, uint8_t *tsb, int64_t *pcrp) t->tht_input_status = TRANSPORT_FEED_NO_DEMUXED_INPUT; - if(tsb[1] & 0x80) - return; /* Transport Error Indicator */ - + if(tsb[1] & 0x80) { + /* Transport Error Indicator */ + limitedlog(&t->tht_loglimit_tei, "TS", transport_nicename(t), + "Transport error indicator"); + return; + } t->tht_input_status = TRANSPORT_FEED_RAW_INPUT; pid = (tsb[1] & 0x1f) << 8 | tsb[2]; diff --git a/src/tvhead.h b/src/tvhead.h index cdac067b..1ec7c276 100644 --- a/src/tvhead.h +++ b/src/tvhead.h @@ -119,7 +119,16 @@ LIST_HEAD(dvr_autorec_entry_list, dvr_autorec_entry); TAILQ_HEAD(th_pktref_queue, th_pktref); LIST_HEAD(streaming_target_list, streaming_target); +/** + * Log limiter + */ +typedef struct loglimter { + time_t last; + int events; +} loglimiter_t; +void limitedlog(loglimiter_t *ll, const char *sys, + const char *o, const char *event); /** * Stream component types @@ -348,6 +357,13 @@ typedef struct th_stream { int st_delete_me; /* Temporary flag for deleting streams */ + /* Error log limiters */ + + loglimiter_t st_loglimit_cc; + loglimiter_t st_loglimit_pes; + + char *st_nicename; + } th_stream_t; @@ -498,6 +514,11 @@ typedef struct th_transport { */ char *tht_identifier; + /** + * Name usable for displaying to user + */ + char *tht_nicename; + /** * Service ID according to EN 300 468 */ @@ -663,6 +684,8 @@ typedef struct th_transport { streaming_pad_t tht_streaming_pad; + loglimiter_t tht_loglimit_tei; + } th_transport_t; diff --git a/src/v4l.c b/src/v4l.c index eff865cf..6069b64c 100644 --- a/src/v4l.c +++ b/src/v4l.c @@ -356,6 +356,7 @@ v4l_transport_find(v4l_adapter_t *va, const char *id, int create) t->tht_iptv_fd = -1; pthread_mutex_lock(&t->tht_stream_mutex); + transport_make_nicename(t); t->tht_video = transport_stream_create(t, -1, SCT_MPEG2VIDEO); t->tht_audio = transport_stream_create(t, -1, SCT_MPEG2AUDIO); pthread_mutex_unlock(&t->tht_stream_mutex);