From 1d50051c5ba01582e29006e77fb90ccebfe3a6a0 Mon Sep 17 00:00:00 2001 From: Frederik Kriewitz Date: Thu, 21 Mar 2024 10:08:50 +0000 Subject: [PATCH] add corrupted_packets_mode option --- config.c | 5 +++-- data.c | 15 ++++++++++++++- data.h | 14 +++++++++++++- input.c | 29 +++++++++++++++++++++++++++++ mptsd_channels.conf | 3 +++ 5 files changed, 62 insertions(+), 4 deletions(-) diff --git a/config.c b/config.c index e12b51a..c283a7c 100644 --- a/config.c +++ b/config.c @@ -134,6 +134,7 @@ int config_load_channels(CONFIG *conf) { } int eit_mode = ini_get_int(ini, 0, "Channel%d:eit_mode", i); + int corrupted_packets_mode = ini_get_int(ini, 0, "Channel%d:corrupted_packets_mode", i); for (j=1;j<8;j++) { char *source = ini_get_string(ini, NULL, "Channel%d:source%d", i, j); @@ -147,7 +148,7 @@ int config_load_channels(CONFIG *conf) { } // Init channel if (channel == NULL) { - channel = channel_new(service_id, is_radio, id, name, eit_mode, source, i, lcn, is_lcn_visible); + channel = channel_new(service_id, is_radio, id, name, eit_mode, corrupted_packets_mode, source, i, lcn, is_lcn_visible); } else { chansrc_add(channel, source); } @@ -227,7 +228,7 @@ int config_load_channels(CONFIG *conf) { if (r->cookie != cookie) { proxy_log(r, "Remove"); /* Replace channel reference with real object and instruct free_restreamer to free it */ - r->channel = channel_new(r->channel->service_id, r->channel->radio, r->channel->id, r->channel->name, r->channel->eit_mode, r->channel->source, r->channel->index, r->channel->lcn, r->channel->lcn_visible); + r->channel = channel_new(r->channel->service_id, r->channel->radio, r->channel->id, r->channel->name, r->channel->eit_mode, r->channel->corrupted_packets_mode, r->channel->source, r->channel->index, r->channel->lcn, r->channel->lcn_visible); r->freechannel = 1; r->dienow = 1; } diff --git a/data.c b/data.c index 02e3ccc..738a9d4 100644 --- a/data.c +++ b/data.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "libfuncs/io.h" #include "libfuncs/log.h" @@ -121,7 +122,7 @@ void chansrc_set(CHANNEL *c, uint8_t src_id) { -CHANNEL *channel_new(int service_id, int is_radio, const char *id, const char *name, int eit_mode, const char *source, int channel_index, int lcn, int is_lcn_visible){ +CHANNEL *channel_new(int service_id, int is_radio, const char *id, const char *name, int eit_mode, int corrupted_packets_mode, const char *source, int channel_index, int lcn, int is_lcn_visible){ if (channel_index<=0 || channel_index>=256) { @@ -142,6 +143,7 @@ CHANNEL *channel_new(int service_id, int is_radio, const char *id, const char *n c->id = strdup(id); c->name = strdup(name); c->eit_mode = eit_mode; + c->corrupted_packets_mode = corrupted_packets_mode; chansrc_add(c, source); @@ -434,6 +436,17 @@ void proxy_log(INPUT *r, char *msg) { LOGf("INPUT : [%-12s] %s fd: %d src: %s\n", r->channel->id, msg, r->sock, r->channel->source); } +void proxy_logf(INPUT *r, const char *fmt, ...) { + char msg[1024]; + va_list args; + va_start(args, fmt); + vsnprintf(msg, sizeof(msg) - 1, fmt, args); + va_end(args); + msg[sizeof(msg) - 1] = '\0'; + + proxy_log(r, msg); +} + void proxy_close(LIST *inputs, INPUT **input) { proxy_log(*input, "Stop"); // If there are no clients left, no "Timeout" messages will be logged diff --git a/data.h b/data.h index 6ca8335..327cf2d 100644 --- a/data.h +++ b/data.h @@ -35,6 +35,11 @@ #include "pidref.h" +typedef struct { + uint64_t count; + uint64_t events; +} CORRUPTION_STATS; + typedef enum { udp_sock, tcp_sock } channel_source; typedef struct { @@ -66,6 +71,10 @@ typedef struct { int radio; int lcn; int lcn_visible; + int corrupted_packets_mode; /* 0 = don't check Transport error indicator (default) + 1 = process corrupted TS packets normally + 2 = drop corrupted TS packets + */ char * id; char * name; int eit_mode; /* 0 = ignore EIT data from input @@ -134,6 +143,8 @@ typedef struct { int cookie; /* Used in chanconf to determine if the restreamer is alrady checked */ int ifd; + CORRUPTION_STATS corruption_stats; + pthread_t thread; uint16_t output_pcr_pid; @@ -231,7 +242,7 @@ EPG_ENTRY * epg_new (time_t start, int duration, char *encoding, char *event, void epg_free (EPG_ENTRY **e); int epg_changed (EPG_ENTRY *a, EPG_ENTRY *b); -CHANNEL * channel_new (int service_id, int is_radio, const char *id, const char *name, int eit_mode, const char *source, int channel_index, int lcn, int is_lcn_visible); +CHANNEL * channel_new (int service_id, int is_radio, const char *id, const char *name, int eit_mode, int corrupted_packets_mode, const char *source, int channel_index, int lcn, int is_lcn_visible); void channel_free (CHANNEL **c); void channel_free_epg(CHANNEL *c); @@ -259,6 +270,7 @@ NIT * nit_new (uint16_t ts_id, char *freq, char *modulation, char *symbol_rat void nit_free (NIT **nit); void proxy_log (INPUT *r, char *msg); +void proxy_logf (INPUT *r, const char *fmt, ...); void proxy_close (LIST *inputs, INPUT **input); #endif diff --git a/input.c b/input.c index f6d55d7..7be2e0d 100644 --- a/input.c +++ b/input.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "libfuncs/io.h" #include "libfuncs/log.h" @@ -417,6 +418,7 @@ void * input_stream(void *self) { ssize_t readen; int max_zero_reads = MAX_ZERO_READS; + uint64_t corrupted_packets = 0; // Reset all stream parameters on reconnect. input_stream_reset(r); @@ -462,6 +464,33 @@ void * input_stream(void *self) { if (r->dienow) goto QUIT; uint8_t *ts_packet = (uint8_t *)buf + i; + + // handle packets with Transport error indicator (TEI) set + if (r->channel->corrupted_packets_mode > 0) { + if (ts_packet_is_tei_set(ts_packet)) { + if (!corrupted_packets) { + r->corruption_stats.events++; + proxy_log(r, "corrupted package received"); + } + if (corrupted_packets % 1000 == 0) { + proxy_logf( + r, "still getting corrupt input packets (%" PRIu64 ")", + corrupted_packets); + } + r->corruption_stats.count++; + corrupted_packets += 1; + if (r->channel->corrupted_packets_mode == 2) { + // drop corrupted TS packet + continue; + } + } else if (corrupted_packets) { + proxy_logf(r, + "corruption ended after %" PRIu64 " packets", + corrupted_packets); + corrupted_packets = 0; + } + } + uint16_t pid = ts_packet_get_pid(ts_packet); int pat_result = process_pat(r, pid, ts_packet); diff --git a/mptsd_channels.conf b/mptsd_channels.conf index 6ec58ff..9bfb41e 100644 --- a/mptsd_channels.conf +++ b/mptsd_channels.conf @@ -8,6 +8,9 @@ id = btv name = bTV eit_mode = 0 # 0 = ignore EIT data from input # 1 = forward EIT data for the configured service, ignore any other EIT data +corrupted_packets_mode = 0 # 0 = don't check Transport error indicator (default) + # 1 = process corrupted TS packets normally + # 2 = drop corrupted TS packets source1 = http://signal-server/stb/btv.mpg #source2 = http://signal-server2/stb/btv.mpg #source3 = http://signal-server3/stb/btv.mpg