From 422fa67876a3a798efd9dbef5481179061d30991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Sat, 9 Jan 2010 16:40:28 +0000 Subject: [PATCH] * More intelligent arbitration amongst all sources when a subscription is about to start for a channel. If we cannot descramble or if no input is detected, skip to next source. Fixes ticket #89 --- debian/changelog | 5 ++++ src/subscriptions.c | 2 +- src/transports.c | 69 +++++++++++++++++++++++++++++++++++++++++---- src/transports.h | 7 ++++- src/tvhead.h | 6 ++++ src/v4l.c | 6 ++++ 6 files changed, 87 insertions(+), 8 deletions(-) diff --git a/debian/changelog b/debian/changelog index c4cfae72..aa1a96bc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -12,6 +12,11 @@ hts-tvheadend (2.8) hts; urgency=low * Improve logging when subscriptions fail to start + * More intelligent arbitration amongst all sources when a subscription + is about to start for a channel. If we cannot descramble or if no + input is detected, skip to next source. + Fixes ticket #89 + hts-tvheadend (2.7) hts; urgency=low * Added support for DVB subtitles. Currently only forwarded over HTSP diff --git a/src/subscriptions.c b/src/subscriptions.c index fcc5c5b5..22c461c9 100644 --- a/src/subscriptions.c +++ b/src/subscriptions.c @@ -291,7 +291,7 @@ subscription_create_from_transport(th_transport_t *t, const char *name, source_info_t si; if(t->tht_status != TRANSPORT_RUNNING) { - if(transport_start(t, INT32_MAX, 1)) { + if(transport_start(t, INT32_MAX, 1, 0)) { subscription_unsubscribe(s); tvhlog(LOG_INFO, "subscription", diff --git a/src/transports.c b/src/transports.c index 1fe672bf..049ee0f7 100644 --- a/src/transports.c +++ b/src/transports.c @@ -66,6 +66,11 @@ transport_nostart2txt(int code) case TRANSPORT_NOSTART_TUNING_FAILED: return "Tuning failed"; case TRANSPORT_NOSTART_SVC_NOT_ENABLED: return "No service enabled"; case TRANSPORT_NOSTART_BAD_SIGNAL: return "Too bad signal quality"; + case TRANSPORT_NOSTART_NO_ACCESS: return "No access"; + case TRANSPORT_NOSTART_NO_DESCRAMBLER: return "No descrambler available"; + case TRANSPORT_NOSTART_NO_INPUT: return "No input detected"; + case TRANSPORT_NOSTART_NO_SIGNAL: return "No signal"; + } return "Unknown error"; } @@ -257,10 +262,11 @@ transport_remove_subscriber(th_transport_t *t, th_subscription_t *s) * */ int -transport_start(th_transport_t *t, unsigned int weight, int force_start) +transport_start(th_transport_t *t, unsigned int weight, int force_start, + int wait_for_ok) { th_stream_t *st; - int r; + int r, err; lock_assert(&global_lock); @@ -287,8 +293,56 @@ transport_start(th_transport_t *t, unsigned int weight, int force_start) cwc_transport_start(t); capmt_transport_start(t); - gtimer_arm(&t->tht_receive_timer, transport_data_timeout, t, 10); - return 0; + int timeout = 10; + + gtimer_arm(&t->tht_receive_timer, transport_data_timeout, t, timeout); + + if(!wait_for_ok) + return 0; + + tvhlog(LOG_DEBUG, "Transport", "%s: Waiting for input before start", + transport_nicename(t)); + + pthread_mutex_lock(&t->tht_stream_mutex); + + struct timespec to; + + to.tv_sec = time(NULL) + timeout; + to.tv_nsec = 0; + + do { + if(t->tht_streaming_status & TSS_MUX_PACKETS) { + tvhlog(LOG_DEBUG, "Transport", "%s: Got demultiplexable packets", + transport_nicename(t)); + pthread_mutex_unlock(&t->tht_stream_mutex); + return 0; + } + + } while(pthread_cond_timedwait(&t->tht_tss_cond, &t->tht_stream_mutex, + &to) != ETIMEDOUT); + + err = t->tht_streaming_status; + + // Startup timed out + + pthread_mutex_unlock(&t->tht_stream_mutex); + + transport_stop(t); + + // Translate streaming status flags to NOSTART errorcode + if(err & TSS_NO_DESCRAMBLER) + return TRANSPORT_NOSTART_NO_DESCRAMBLER; + + if(err & TSS_NO_ACCESS) + return TRANSPORT_NOSTART_NO_ACCESS; + + if(err & TSS_NO_ACCESS) + return TRANSPORT_NOSTART_NO_ACCESS; + + if(err & TSS_INPUT_SERVICE) + return TRANSPORT_NOSTART_NO_INPUT; + + return TRANSPORT_NOSTART_NO_SIGNAL; } @@ -408,7 +462,7 @@ transport_find(channel_t *ch, unsigned int weight, const char *loginfo, if(t->tht_status == TRANSPORT_RUNNING) return t; - if(!transport_start(t, 0, 0)) + if(!transport_start(t, 0, 0, 1)) return t; } @@ -417,7 +471,7 @@ transport_find(channel_t *ch, unsigned int weight, const char *loginfo, for(i = 0; i < cnt; i++) { t = vec[i]; - if((r = transport_start(t, weight, 0)) == 0) + if((r = transport_start(t, weight, 0, 1)) == 0) return t; error = r; if(loginfo != NULL) @@ -534,6 +588,7 @@ transport_create(const char *identifier, int type, int source_type) lock_assert(&global_lock); pthread_mutex_init(&t->tht_stream_mutex, NULL); + pthread_cond_init(&t->tht_tss_cond, NULL); t->tht_identifier = strdup(identifier); t->tht_type = type; t->tht_source_type = source_type; @@ -790,6 +845,8 @@ transport_set_streaming_status_flags(th_transport_t *t, int set) t->tht_streaming_status); streaming_pad_deliver(&t->tht_streaming_pad, sm); streaming_msg_free(sm); + + pthread_cond_broadcast(&t->tht_tss_cond); } diff --git a/src/transports.h b/src/transports.h index 5ae87532..8e27b7c8 100644 --- a/src/transports.h +++ b/src/transports.h @@ -29,12 +29,17 @@ #define TRANSPORT_NOSTART_TUNING_FAILED 4 #define TRANSPORT_NOSTART_SVC_NOT_ENABLED 5 #define TRANSPORT_NOSTART_BAD_SIGNAL 6 +#define TRANSPORT_NOSTART_NO_ACCESS 7 +#define TRANSPORT_NOSTART_NO_DESCRAMBLER 8 +#define TRANSPORT_NOSTART_NO_INPUT 9 +#define TRANSPORT_NOSTART_NO_SIGNAL 10 void transport_init(void); unsigned int transport_compute_weight(struct th_transport_list *head); -int transport_start(th_transport_t *t, unsigned int weight, int force_start); +int transport_start(th_transport_t *t, unsigned int weight, int force_start, + int wait_for_ok); th_transport_t *transport_create(const char *identifier, int type, int source_type); diff --git a/src/tvhead.h b/src/tvhead.h index e7f7bf85..3d9cc3c6 100644 --- a/src/tvhead.h +++ b/src/tvhead.h @@ -597,6 +597,12 @@ typedef struct th_transport { */ pthread_mutex_t tht_stream_mutex; + + /** + * Condition variable to singal when streaming_status changes + * interlocked with tht_stream_mutex + */ + pthread_cond_t tht_tss_cond; /** * */ diff --git a/src/v4l.c b/src/v4l.c index 6069b64c..4b5ac648 100644 --- a/src/v4l.c +++ b/src/v4l.c @@ -66,6 +66,9 @@ v4l_input(v4l_adapter_t *va) pthread_mutex_lock(&t->tht_stream_mutex); + transport_set_streaming_status_flags(t, + TSS_INPUT_HARDWARE | TSS_INPUT_SERVICE); + while(len > 0) { switch(va->va_startcode) { @@ -97,6 +100,9 @@ v4l_input(v4l_adapter_t *va) st->st_buffer2_ptr += r; if(st->st_buffer2_ptr == l) { + + transport_set_streaming_status_flags(t, TSS_MUX_PACKETS); + parse_mpeg_ps(t, st, pkt + 6, l - 6); st->st_buffer2_size = 0;