diff --git a/src/dvr/dvr_rec.c b/src/dvr/dvr_rec.c index 6d9eb743..412dbede 100644 --- a/src/dvr/dvr_rec.c +++ b/src/dvr/dvr_rec.c @@ -435,9 +435,12 @@ dvr_thread(void *aux) break; case SMT_TRANSPORT_STATUS: - if(sm->sm_code != TRANSPORT_FEED_VALID_PACKETS) + if(sm->sm_code & TSS_PACKETS) { + + } else if(sm->sm_code & (TSS_GRACEPERIOD | TSS_ERRORS)) { dvr_rec_fatal_error(de, "Source problems: %s", - transport_feed_status_to_text(sm->sm_code)); + transport_tss2text(sm->sm_code)); + } break; case SMT_NOSOURCE: diff --git a/src/htsp.c b/src/htsp.c index f9dd00d3..af1b7220 100644 --- a/src/htsp.c +++ b/src/htsp.c @@ -1478,17 +1478,14 @@ htsp_subscription_status(htsp_subscription_t *hs, const char *err) * */ static void -htsp_subscription_transport_status(htsp_subscription_t *hs, - transport_feed_status_t status) +htsp_subscription_transport_status(htsp_subscription_t *hs, int status) { - const char *err = NULL; - - if(status != TRANSPORT_FEED_VALID_PACKETS) - err = transport_feed_status_to_text(status); - - htsp_subscription_status(hs, err); + if(status & TSS_PACKETS) { + htsp_subscription_status(hs, NULL); + } else if(status & (TSS_GRACEPERIOD | TSS_ERRORS)) { + htsp_subscription_status(hs, transport_tss2text(status)); + } } - /** * diff --git a/src/parsers.c b/src/parsers.c index 650048cd..08c9df1c 100644 --- a/src/parsers.c +++ b/src/parsers.c @@ -1095,7 +1095,7 @@ parser_deliver(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt, /** * Input is ok */ - transport_set_feed_status(t, TRANSPORT_FEED_VALID_PACKETS); + transport_set_streaming_status_flags(t, TSS_PACKETS); /* Forward packet */ pkt->pkt_componentindex = st->st_index; diff --git a/src/psi.c b/src/psi.c index 7f637e70..7cd25d59 100644 --- a/src/psi.c +++ b/src/psi.c @@ -365,7 +365,7 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid, len -= 5; frameduration = 0; - hts_stream_type = 0; + hts_stream_type = SCT_UNKNOWN; memset(lang, 0, 4); composition_id = -1; ancillary_id = -1; @@ -452,7 +452,7 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid, len -= dlen; ptr += dlen; dllen -= dlen; } - if(hts_stream_type != 0) { + if(hts_stream_type != SCT_UNKNOWN) { if((st = transport_stream_find(t, pid)) == NULL) { update |= PMT_UPDATE_NEW_STREAM; diff --git a/src/serviceprobe.c b/src/serviceprobe.c index 8d079382..a431218e 100644 --- a/src/serviceprobe.c +++ b/src/serviceprobe.c @@ -84,7 +84,7 @@ serviceprobe_thread(void *aux) int was_doing_work = 0; streaming_queue_t sq; streaming_message_t *sm; - transport_feed_status_t status; + // transport_feed_status_t status; int run; const char *err; channel_t *ch; @@ -136,14 +136,14 @@ serviceprobe_thread(void *aux) pthread_mutex_unlock(&sq.sq_mutex); if(sm->sm_type == SMT_TRANSPORT_STATUS) { - status = sm->sm_code; + int status = sm->sm_code; - run = 0; - - if(status == TRANSPORT_FEED_VALID_PACKETS) { + if(status & TSS_PACKETS) { + run = 0; err = NULL; - } else { - err = transport_feed_status_to_text(status); + } else if(status & (TSS_GRACEPERIOD | TSS_ERRORS)) { + run = 0; + err = transport_tss2text(status); } } diff --git a/src/subscriptions.c b/src/subscriptions.c index e522b37b..fcc5c5b5 100644 --- a/src/subscriptions.c +++ b/src/subscriptions.c @@ -68,11 +68,10 @@ static void subscription_link_transport(th_subscription_t *s, th_transport_t *t) { streaming_message_t *sm; - + s->ths_transport = t; LIST_INSERT_HEAD(&t->tht_subscriptions, s, ths_transport_link); - pthread_mutex_lock(&t->tht_stream_mutex); // Link to transport output @@ -87,10 +86,12 @@ subscription_link_transport(th_subscription_t *s, th_transport_t *t) streaming_target_deliver(s->ths_output, sm); // Send a TRANSPORT_STATUS message to the subscription client - if(t->tht_feed_status != TRANSPORT_FEED_UNKNOWN) { - sm = streaming_msg_create_code(SMT_TRANSPORT_STATUS, t->tht_feed_status); + if(t->tht_streaming_status) { + sm = streaming_msg_create_code(SMT_TRANSPORT_STATUS, + t->tht_streaming_status); streaming_target_deliver(s->ths_output, sm); } + } pthread_mutex_unlock(&t->tht_stream_mutex); } @@ -334,8 +335,7 @@ dummy_callback(void *opauqe, streaming_message_t *sm) break; case SMT_TRANSPORT_STATUS: - fprintf(stderr, "dummsubscription: %s\n", - transport_feed_status_to_text(sm->sm_code)); + fprintf(stderr, "dummsubscription: %x\n", sm->sm_code); break; default: break; diff --git a/src/transports.c b/src/transports.c index f9ae02b1..1fe672bf 100644 --- a/src/transports.c +++ b/src/transports.c @@ -265,9 +265,7 @@ transport_start(th_transport_t *t, unsigned int weight, int force_start) lock_assert(&global_lock); assert(t->tht_status != TRANSPORT_RUNNING); - - t->tht_feed_status = TRANSPORT_FEED_UNKNOWN; - t->tht_input_status = TRANSPORT_FEED_NO_INPUT; + t->tht_streaming_status = 0; t->tht_dts_start = AV_NOPTS_VALUE; t->tht_pcr_drift = 0; @@ -713,7 +711,6 @@ transport_map_channel(th_transport_t *t, channel_t *ch, int save) t->tht_config_save(t); } - /** * */ @@ -724,13 +721,11 @@ transport_data_timeout(void *aux) pthread_mutex_lock(&t->tht_stream_mutex); - if(t->tht_feed_status == TRANSPORT_FEED_UNKNOWN) - transport_set_feed_status(t, t->tht_input_status); + transport_set_streaming_status_flags(t, TSS_GRACEPERIOD); pthread_mutex_unlock(&t->tht_stream_mutex); } - /** * */ @@ -766,17 +761,33 @@ transport_is_tv(th_transport_t *t) * */ void -transport_set_feed_status(th_transport_t *t, transport_feed_status_t newstatus) +transport_set_streaming_status_flags(th_transport_t *t, int set) { + int n; + streaming_message_t *sm; lock_assert(&t->tht_stream_mutex); + + n = t->tht_streaming_status; + + n |= set; - if(t->tht_feed_status == newstatus) - return; + if(n == t->tht_streaming_status) + return; // Already set - t->tht_feed_status = newstatus; + t->tht_streaming_status = n; - streaming_message_t *sm = streaming_msg_create_code(SMT_TRANSPORT_STATUS, - newstatus); + tvhlog(LOG_DEBUG, "Transport", "%s: Status changed to %s%s%s%s%s%s%s", + transport_nicename(t), + n & TSS_INPUT_HARDWARE ? "[Hardware input] " : "", + n & TSS_INPUT_SERVICE ? "[Input on service] " : "", + n & TSS_MUX_PACKETS ? "[Demuxed packets] " : "", + n & TSS_PACKETS ? "[Reassembled packets] " : "", + n & TSS_NO_DESCRAMBLER ? "[No available descrambler] " : "", + n & TSS_NO_ACCESS ? "[No access] " : "", + n & TSS_GRACEPERIOD ? "[Graceperiod expired] " : ""); + + sm = streaming_msg_create_code(SMT_TRANSPORT_STATUS, + t->tht_streaming_status); streaming_pad_deliver(&t->tht_streaming_pad, sm); streaming_msg_free(sm); } @@ -848,42 +859,6 @@ transport_build_stream_start(th_transport_t *t) } - - -/** - * Table for status -> text conversion - */ -static struct strtab transportstatustab[] = { - { "Unknown", - TRANSPORT_FEED_UNKNOWN }, - - { "No data input from adapter detected", - TRANSPORT_FEED_NO_INPUT}, - - {"No mux packets for this service", - TRANSPORT_FEED_NO_DEMUXED_INPUT}, - - {"Data received for service, but no packets could be reassembled", - TRANSPORT_FEED_RAW_INPUT}, - - {"No descrambler available for service", - TRANSPORT_FEED_NO_DESCRAMBLER}, - - {"Access denied", - TRANSPORT_FEED_NO_ACCESS}, - - {"OK", - TRANSPORT_FEED_VALID_PACKETS}, -}; - - -const char * -transport_feed_status_to_text(transport_feed_status_t status) -{ - return val2str(status, transportstatustab) ?: "Unknown"; -} - - /** * */ @@ -1013,3 +988,30 @@ transport_component_nicename(th_stream_t *st) { return st->st_nicename; } + +const char * +transport_tss2text(int flags) +{ + if(flags & TSS_NO_ACCESS) + return "No access"; + + if(flags & TSS_NO_DESCRAMBLER) + return "No descrambler"; + + if(flags & TSS_PACKETS) + return "Got valid packets"; + + if(flags & TSS_MUX_PACKETS) + return "Got multiplexed packets but could not decode further"; + + if(flags & TSS_INPUT_SERVICE) + return "Got packets for this service but could not decode further"; + + if(flags & TSS_INPUT_HARDWARE) + return "Sensed input from hardware but nothing for the service"; + + if(flags & TSS_GRACEPERIOD) + return "No input detected"; + + return "No status"; +} diff --git a/src/transports.h b/src/transports.h index c215a9b0..5ae87532 100644 --- a/src/transports.h +++ b/src/transports.h @@ -65,13 +65,10 @@ int transport_is_tv(th_transport_t *t); void transport_destroy(th_transport_t *t); -void transport_set_feed_status(th_transport_t *t, - transport_feed_status_t newstatus); - -const char *transport_feed_status_to_text(transport_feed_status_t status); - void transport_remove_subscriber(th_transport_t *t, th_subscription_t *s); +void transport_set_streaming_status_flags(th_transport_t *t, int flag); + static inline th_stream_t * transport_find_stream_by_pid(th_transport_t *t, int pid) { @@ -107,4 +104,11 @@ const char *transport_component_nicename(th_stream_t *st); const char *transport_nostart2txt(int code); +const char *transport_tss2text(int flags); + +static inline int transport_tss_is_error(int flags) +{ + return flags & TSS_ERRORS ? 1 : 0; +} + #endif /* TRANSPORTS_H */ diff --git a/src/tsdemux.c b/src/tsdemux.c index 20e7c1b0..3beb76b8 100644 --- a/src/tsdemux.c +++ b/src/tsdemux.c @@ -73,6 +73,8 @@ ts_recv_packet0(th_transport_t *t, th_stream_t *st, uint8_t *tsb) { int off, len, pusi, cc, err = 0; + transport_set_streaming_status_flags(t, TSS_MUX_PACKETS); + if(streaming_pad_probe_type(&t->tht_streaming_pad, SMT_MPEGTS)) ts_remux(t, tsb); @@ -204,19 +206,20 @@ ts_recv_packet1(th_transport_t *t, uint8_t *tsb, int64_t *pcrp) int pid, n, m, r; th_descrambler_t *td; - t->tht_input_status = TRANSPORT_FEED_NO_DEMUXED_INPUT; + pthread_mutex_lock(&t->tht_stream_mutex); + + transport_set_streaming_status_flags(t, TSS_INPUT_HARDWARE); if(tsb[1] & 0x80) { /* Transport Error Indicator */ limitedlog(&t->tht_loglimit_tei, "TS", transport_nicename(t), "Transport error indicator"); + pthread_mutex_unlock(&t->tht_stream_mutex); return; } - t->tht_input_status = TRANSPORT_FEED_RAW_INPUT; pid = (tsb[1] & 0x1f) << 8 | tsb[2]; - pthread_mutex_lock(&t->tht_stream_mutex); st = transport_find_stream_by_pid(t, pid); /* Extract PCR */ @@ -228,6 +231,8 @@ ts_recv_packet1(th_transport_t *t, uint8_t *tsb, int64_t *pcrp) return; } + transport_set_streaming_status_flags(t, TSS_INPUT_SERVICE); + avgstat_add(&t->tht_rate, 188, dispatch_clock); if((tsb[3] & 0xc0) || @@ -253,9 +258,9 @@ ts_recv_packet1(th_transport_t *t, uint8_t *tsb, int64_t *pcrp) } if(n == 0) { - transport_set_feed_status(t, TRANSPORT_FEED_NO_DESCRAMBLER); + transport_set_streaming_status_flags(t, TSS_NO_DESCRAMBLER); } else if(m == n) { - transport_set_feed_status(t, TRANSPORT_FEED_NO_ACCESS); + transport_set_streaming_status_flags(t, TSS_NO_ACCESS); } } else { ts_recv_packet0(t, st, tsb); diff --git a/src/tvhead.h b/src/tvhead.h index 4bafccee..e7f7bf85 100644 --- a/src/tvhead.h +++ b/src/tvhead.h @@ -134,6 +134,7 @@ void limitedlog(loglimiter_t *ll, const char *sys, * Stream component types */ typedef enum { + SCT_UNKNOWN = 0, SCT_MPEG2VIDEO = 1, SCT_MPEG2AUDIO, SCT_H264, @@ -176,7 +177,7 @@ typedef enum { SMT_START, // sm_data is a stream_start, // see transport_build_stream_start() SMT_STOP , // no extra payload right now - SMT_TRANSPORT_STATUS, // sm_code is TRANSPORT_STATUS_ + SMT_TRANSPORT_STATUS, // sm_code is TSS_ ...something SMT_EXIT, // Used to signal exit to threads SMT_NOSOURCE, SMT_MPEGTS, // sm_data is raw MPEG TS @@ -367,35 +368,6 @@ typedef struct th_stream { } th_stream_t; -/** - * - */ -typedef enum { - - /** No status known */ - TRANSPORT_FEED_UNKNOWN, - - /** No packets are received from source at all */ - TRANSPORT_FEED_NO_INPUT, - - /** No input is received from source destined for this transport */ - TRANSPORT_FEED_NO_DEMUXED_INPUT, - - /** Raw input seen but nothing has really been decoded */ - TRANSPORT_FEED_RAW_INPUT, - - /** No descrambler is able to decrypt the stream */ - TRANSPORT_FEED_NO_DESCRAMBLER, - - /** Potential descrambler is available, but access is denied */ - TRANSPORT_FEED_NO_ACCESS, - - /** Packet are being parsed. */ - TRANSPORT_FEED_VALID_PACKETS, - -} transport_feed_status_t; - - /** * A Transport (or in MPEG TS terms: a 'service') */ @@ -626,14 +598,23 @@ typedef struct th_transport { pthread_mutex_t tht_stream_mutex; /** - * Last known data status (or error) + * */ - transport_feed_status_t tht_feed_status; + int tht_streaming_status; - /** - * Set as soon as we get some kind of activity - */ - transport_feed_status_t tht_input_status; + // Progress +#define TSS_INPUT_HARDWARE 0x1 +#define TSS_INPUT_SERVICE 0x2 +#define TSS_MUX_PACKETS 0x4 +#define TSS_PACKETS 0x8 + +#define TSS_GRACEPERIOD 0x8000 + + // Errors +#define TSS_NO_DESCRAMBLER 0x10000 +#define TSS_NO_ACCESS 0x20000 + +#define TSS_ERRORS 0xffff0000 /**