Use flags to signal transport status

This commit is contained in:
Andreas Öman 2010-01-09 16:03:26 +00:00
parent 7ae41b62ce
commit 62008fcb9d
10 changed files with 114 additions and 122 deletions

View file

@ -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:

View file

@ -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));
}
}
/**
*

View file

@ -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;

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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";
}

View file

@ -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 */

View file

@ -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);

View file

@ -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
/**