From d760c4cb7cf9bac30292cd21f9df08563ecdbd1f Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 12 Dec 2014 11:19:26 +0100 Subject: [PATCH] implement TSS_TUNING message for late tuning error notification (SAT>IP) --- src/dvr/dvr_rec.c | 3 +- src/htsp_server.c | 2 +- src/input/mpegts.h | 3 ++ src/input/mpegts/mpegts_input.c | 30 +++++++++++----- src/input/mpegts/mpegts_mux.c | 22 +++++++++++- src/input/mpegts/satip/satip_frontend.c | 46 ++++++++++++++++++------- src/service.c | 9 ++++- src/service.h | 7 ++-- src/service_mapper.c | 2 +- src/subscriptions.c | 4 +-- 10 files changed, 97 insertions(+), 31 deletions(-) diff --git a/src/dvr/dvr_rec.c b/src/dvr/dvr_rec.c index 950fe8aa..71631b65 100644 --- a/src/dvr/dvr_rec.c +++ b/src/dvr/dvr_rec.c @@ -576,11 +576,10 @@ dvr_thread(void *aux) case SMT_SERVICE_STATUS: if(sm->sm_code & TSS_PACKETS) { - } else if(sm->sm_code & (TSS_GRACEPERIOD | TSS_ERRORS)) { + } else if(sm->sm_code & TSS_ERRORS) { int code = SM_CODE_UNDEFINED_ERROR; - if(sm->sm_code & TSS_NO_DESCRAMBLER) code = SM_CODE_NO_DESCRAMBLER; diff --git a/src/htsp_server.c b/src/htsp_server.c index 69558f73..d7b2e0e9 100644 --- a/src/htsp_server.c +++ b/src/htsp_server.c @@ -3184,7 +3184,7 @@ htsp_subscription_service_status(htsp_subscription_t *hs, int status) { if(status & TSS_PACKETS) { htsp_subscription_status(hs, NULL); - } else if(status & (TSS_GRACEPERIOD | TSS_ERRORS)) { + } else if(status & TSS_ERRORS) { htsp_subscription_status(hs, service_tss2text(status)); } } diff --git a/src/input/mpegts.h b/src/input/mpegts.h index c5ea0148..2a000fa0 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -631,6 +631,7 @@ struct mpegts_input void (*mi_stopping_mux) (mpegts_input_t*,mpegts_mux_instance_t*); void (*mi_stopped_mux) (mpegts_input_t*,mpegts_mux_instance_t*); int (*mi_has_subscription) (mpegts_input_t*, mpegts_mux_t *mm); + void (*mi_tuning_error) (mpegts_input_t*,mpegts_mux_t *); idnode_set_t *(*mi_network_list) (mpegts_input_t*); }; @@ -748,6 +749,8 @@ void mpegts_mux_delete ( mpegts_mux_t *mm, int delconf ); void mpegts_mux_save ( mpegts_mux_t *mm, htsmsg_t *c ); +void mpegts_mux_tuning_error( mpegts_mux_t *mm ); + mpegts_mux_instance_t *mpegts_mux_instance_create0 ( mpegts_mux_instance_t *mmi, const idclass_t *class, const char *uuid, mpegts_input_t *mi, mpegts_mux_t *mm ); diff --git a/src/input/mpegts/mpegts_input.c b/src/input/mpegts/mpegts_input.c index 6896a0e7..33e80856 100644 --- a/src/input/mpegts/mpegts_input.c +++ b/src/input/mpegts/mpegts_input.c @@ -544,7 +544,7 @@ mpegts_input_stopped_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi ) { char buf[256]; - service_t *s; + service_t *s, *s_next; /* no longer active */ LIST_REMOVE(mmi, mmi_active_link); @@ -555,11 +555,10 @@ mpegts_input_stopped_mux mi->mi_display_name(mi, buf, sizeof(buf)); tvhtrace("mpegts", "%s - flush subscribers", buf); - s = LIST_FIRST(&mi->mi_transports); - while (s) { + for (s = LIST_FIRST(&mi->mi_transports); s; s = s_next) { + s_next = LIST_NEXT(s, s_active_link); if (((mpegts_service_t*)s)->s_dvb_mux == mmi->mmi_mux) service_remove_subscriber(s, NULL, SM_CODE_SUBSCRIPTION_OVERRIDDEN); - s = LIST_NEXT(s, s_active_link); } notify_reload("input_status"); mpegts_input_dbus_notify(mi, 0); @@ -597,6 +596,22 @@ mpegts_input_has_subscription ( mpegts_input_t *mi, mpegts_mux_t *mm ) return ret; } +static void +mpegts_input_tuning_error ( mpegts_input_t *mi, mpegts_mux_t *mm ) +{ + service_t *t, *t_next; + pthread_mutex_lock(&mi->mi_output_lock); + for (t = LIST_FIRST(&mi->mi_transports); t; t = t_next) { + t_next = LIST_NEXT(t, s_active_link); + if (((mpegts_service_t*)t)->s_dvb_mux == mm) { + pthread_mutex_lock(&t->s_stream_mutex); + service_set_streaming_status_flags(t, TSS_TUNING); + pthread_mutex_unlock(&t->s_stream_mutex); + } + } + pthread_mutex_unlock(&mi->mi_output_lock); +} + /* ************************************************************************** * Data processing * *************************************************************************/ @@ -867,9 +882,6 @@ mpegts_input_process goto done; } - /* Remove in future or move it outside this loop */ - lock_assert(&mi->mi_output_lock); - /* Find PID */ if ((mp = mpegts_mux_find_pid(mm, pid, 0))) { @@ -1259,6 +1271,7 @@ mpegts_input_create0 mi->mi_stopping_mux = mpegts_input_stopping_mux; mi->mi_stopped_mux = mpegts_input_stopped_mux; mi->mi_has_subscription = mpegts_input_has_subscription; + mi->mi_tuning_error = mpegts_input_tuning_error; mi->ti_get_streams = mpegts_input_get_streams; /* Index */ @@ -1405,7 +1418,8 @@ mpegts_input_set_networks ( mpegts_input_t *mi, htsmsg_t *msg ) return save; } -int mpegts_input_grace( mpegts_input_t *mi, mpegts_mux_t *mm ) +int +mpegts_input_grace( mpegts_input_t *mi, mpegts_mux_t *mm ) { /* Get timeout */ int t = 0; diff --git a/src/input/mpegts/mpegts_mux.c b/src/input/mpegts/mpegts_mux.c index 246ae15b..ba11b044 100644 --- a/src/input/mpegts/mpegts_mux.c +++ b/src/input/mpegts/mpegts_mux.c @@ -21,6 +21,7 @@ #include "queue.h" #include "input.h" #include "subscriptions.h" +#include "streaming.h" #include "channels.h" #include "access.h" #include "profile.h" @@ -1111,12 +1112,31 @@ mpegts_mux_unsubscribe_by_name } } +void +mpegts_mux_tuning_error ( mpegts_mux_t *mm ) +{ + th_subscription_t *sub; + mpegts_mux_instance_t *mmi; + streaming_message_t *sm; + + lock_assert(&global_lock); + + if ((mmi = mm->mm_active) != NULL) { + LIST_FOREACH(sub, &mmi->mmi_subs, ths_mmi_link) { + sm = streaming_msg_create_code(SMT_SERVICE_STATUS, TSS_TUNING); + streaming_target_deliver(sub->ths_output, sm); + } + if (mmi->mmi_input) + mmi->mmi_input->mi_tuning_error(mmi->mmi_input, mm); + } +} + /* ************************************************************************** * Search * *************************************************************************/ mpegts_service_t * -mpegts_mux_find_service ( mpegts_mux_t *mm, uint16_t sid) +mpegts_mux_find_service ( mpegts_mux_t *mm, uint16_t sid ) { mpegts_service_t *ms; LIST_FOREACH(ms, &mm->mm_services, s_dvb_mux_link) diff --git a/src/input/mpegts/satip/satip_frontend.c b/src/input/mpegts/satip/satip_frontend.c index d1547131..b910b58e 100644 --- a/src/input/mpegts/satip/satip_frontend.c +++ b/src/input/mpegts/satip/satip_frontend.c @@ -999,6 +999,18 @@ satip_frontend_pid_changed( http_client_t *rtsp, return r; } +static void +satip_frontend_tuning_error ( satip_frontend_t *lfe, satip_tune_req_t *tr ) +{ + pthread_mutex_lock(&global_lock); + pthread_mutex_lock(&lfe->sf_dvr_lock); + if (lfe->sf_running && lfe->sf_req == tr && + tr->sf_mmi && tr->sf_mmi->mmi_mux) + mpegts_mux_tuning_error(tr->sf_mmi->mmi_mux); + pthread_mutex_unlock(&lfe->sf_dvr_lock); + pthread_mutex_unlock(&global_lock); +} + static void * satip_frontend_input_thread ( void *aux ) { @@ -1086,7 +1098,7 @@ new_tune: mmi = tr->sf_mmi; changing = 0; - ms = -1; + ms = 500; fatal = 0; running = 1; seq = -1; @@ -1096,8 +1108,10 @@ new_tune: if (udp_bind_double(&rtp, &rtcp, "satip", "rtp", "rtpc", satip_frontend_bindaddr(lfe), lfe->sf_udp_rtp_port, - NULL, SATIP_BUF_SIZE, 16384) < 0) + NULL, SATIP_BUF_SIZE, 16384) < 0) { + satip_frontend_tuning_error(lfe, tr); goto done; + } rtp_port = ntohs(IP_PORT(rtp->ip)); @@ -1106,8 +1120,10 @@ new_tune: ntohs(IP_PORT(rtp->ip)), ntohs(IP_PORT(rtcp->ip))); - if (rtp == NULL || rtcp == NULL || mmi == NULL) + if (rtp == NULL || rtcp == NULL || mmi == NULL) { + satip_frontend_tuning_error(lfe, tr); goto done; + } lm = (dvb_mux_t *)mmi->mmi_mux; @@ -1176,8 +1192,10 @@ new_tune: rtsp = http_client_connect(lfe, RTSP_VERSION_1_0, "rstp", lfe->sf_device->sd_info.addr, 554, satip_frontend_bindaddr(lfe)); - if (rtsp == NULL) + if (rtsp == NULL) { + satip_frontend_tuning_error(lfe, tr); goto done; + } /* Setup poll */ memset(ev, 0, sizeof(ev)); @@ -1198,7 +1216,7 @@ new_tune: rtsp_flags |= SATIP_SETUP_PIDS0; if (lfe->sf_device->sd_pilot_on) rtsp_flags |= SATIP_SETUP_PILOT_ON; - r = 0xa59234; + r = -12345678; pthread_mutex_lock(&lfe->sf_dvr_lock); if (lfe->sf_req == lfe->sf_req_thread) r = satip_rtsp_setup(rtsp, @@ -1207,15 +1225,15 @@ new_tune: rtsp_flags); pthread_mutex_unlock(&lfe->sf_dvr_lock); if (r < 0) { - if (r != 0xa59234) - tvherror("satip", "%s - failed to tune", buf); + tvherror("satip", "%s - failed to tune", buf); + satip_frontend_tuning_error(lfe, tr); goto done; } reply = 1; udp_multirecv_init(&um, RTP_PKTS, RTP_PKT_SIZE); sbuf_init_fixed(&sb, RTP_PKTS * RTP_PKT_SIZE); - + while ((reply || running) && !fatal) { nfds = tvhpoll_wait(efd, ev, 1, ms); @@ -1247,7 +1265,7 @@ new_tune: } if (changing && rtsp->hc_cmd == HTTP_CMD_NONE) { - ms = -1; + ms = 500; changing = 0; if (satip_frontend_pid_changed(rtsp, lfe, buf) > 0) reply = 1; @@ -1261,6 +1279,7 @@ new_tune: if (r < 0) { tvhlog(LOG_ERR, "satip", "%s - RTSP error %d (%s) [%i-%i]", buf, r, strerror(-r), rtsp->hc_cmd, rtsp->hc_code); + satip_frontend_tuning_error(lfe, tr); fatal = 1; } else if (r == HTTP_CON_DONE) { reply = 0; @@ -1272,6 +1291,7 @@ new_tune: if (r < 0) { tvhlog(LOG_ERR, "satip", "%s - RTSP OPTIONS error %d (%s) [%i-%i]", buf, r, strerror(-r), rtsp->hc_cmd, rtsp->hc_code); + satip_frontend_tuning_error(lfe, tr); fatal = 1; } break; @@ -1283,13 +1303,14 @@ new_tune: rtsp->hc_rtpc_port != rtp_port + 1) { tvhlog(LOG_ERR, "satip", "%s - RTSP SETUP error %d (%s) [%i-%i]", buf, r, strerror(-r), rtsp->hc_cmd, rtsp->hc_code); + satip_frontend_tuning_error(lfe, tr); fatal = 1; } else { tvhdebug("satip", "%s #%i - new session %s stream id %li", rtsp->hc_host, lfe->sf_number, rtsp->hc_rtsp_session, rtsp->hc_rtsp_stream_id); if (lfe->sf_play2) { - r = 0xa59234; + r = -12345678; pthread_mutex_lock(&lfe->sf_dvr_lock); if (lfe->sf_req == lfe->sf_req_thread) r = satip_rtsp_setup(rtsp, position, lfe->sf_number, @@ -1297,8 +1318,8 @@ new_tune: rtsp_flags | SATIP_SETUP_PLAY); pthread_mutex_unlock(&lfe->sf_dvr_lock); if (r < 0) { - if (r != 0xa59234) - tvherror("satip", "%s - failed to tune2", buf); + tvherror("satip", "%s - failed to tune2", buf); + satip_frontend_tuning_error(lfe, tr); fatal = 1; } reply = 1; @@ -1326,6 +1347,7 @@ new_tune: if (rtsp->hc_code >= 400) { tvhlog(LOG_ERR, "satip", "%s - RTSP cmd error %d (%s) [%i-%i]", buf, r, strerror(-r), rtsp->hc_cmd, rtsp->hc_code); + satip_frontend_tuning_error(lfe, tr); fatal = 1; } break; diff --git a/src/service.c b/src/service.c index 5897d23b..b6bf4582 100644 --- a/src/service.c +++ b/src/service.c @@ -1168,7 +1168,7 @@ service_set_streaming_status_flags_(service_t *t, int set) t->s_streaming_status = set; - tvhlog(LOG_DEBUG, "service", "%s: Status changed to %s%s%s%s%s%s%s%s", + tvhlog(LOG_DEBUG, "service", "%s: Status changed to %s%s%s%s%s%s%s%s%s", service_nicename(t), set & TSS_INPUT_HARDWARE ? "[Hardware input] " : "", set & TSS_INPUT_SERVICE ? "[Input on service] " : "", @@ -1176,6 +1176,7 @@ service_set_streaming_status_flags_(service_t *t, int set) set & TSS_PACKETS ? "[Reassembled packets] " : "", set & TSS_NO_DESCRAMBLER ? "[No available descrambler] " : "", set & TSS_NO_ACCESS ? "[No access] " : "", + set & TSS_TUNING ? "[Tuning failed] " : "", set & TSS_GRACEPERIOD ? "[Graceperiod expired] " : "", set & TSS_TIMEOUT ? "[Data timeout] " : ""); @@ -1448,6 +1449,9 @@ service_tss2text(int flags) if(flags & TSS_NO_ACCESS) return "No access"; + if(flags & TSS_TUNING) + return "Tuning failed"; + if(flags & TSS_NO_DESCRAMBLER) return "No descrambler"; @@ -1482,6 +1486,9 @@ tss2errcode(int tss) if(tss & TSS_NO_ACCESS) return SM_CODE_NO_ACCESS; + if(tss & TSS_TUNING) + return SM_CODE_TUNING_FAILED; + if(tss & TSS_NO_DESCRAMBLER) return SM_CODE_NO_DESCRAMBLER; diff --git a/src/service.h b/src/service.h index d4f4664c..fb8b38f2 100644 --- a/src/service.h +++ b/src/service.h @@ -406,11 +406,12 @@ typedef struct service { #define TSS_PACKETS 0x8 #define TSS_NO_ACCESS 0x10 -#define TSS_GRACEPERIOD 0x8000 // Errors -#define TSS_NO_DESCRAMBLER 0x10000 -#define TSS_TIMEOUT 0x20000 +#define TSS_GRACEPERIOD 0x10000 +#define TSS_NO_DESCRAMBLER 0x20000 +#define TSS_TIMEOUT 0x40000 +#define TSS_TUNING 0x80000 #define TSS_ERRORS 0xffff0000 diff --git a/src/service_mapper.c b/src/service_mapper.c index dafe1591..777da9ec 100644 --- a/src/service_mapper.c +++ b/src/service_mapper.c @@ -414,7 +414,7 @@ service_mapper_thread ( void *aux ) } else if (sm->sm_type == SMT_SERVICE_STATUS) { int status = sm->sm_code; - if(status & (TSS_GRACEPERIOD | TSS_ERRORS)) { + if(status & TSS_ERRORS) { run = 0; err = service_tss2text(status); } diff --git a/src/subscriptions.c b/src/subscriptions.c index 150d4d14..1c0a08b1 100644 --- a/src/subscriptions.c +++ b/src/subscriptions.c @@ -464,7 +464,7 @@ subscription_input(void *opauqe, streaming_message_t *sm) } if(sm->sm_type == SMT_SERVICE_STATUS && - sm->sm_code & (TSS_GRACEPERIOD | TSS_ERRORS)) { + sm->sm_code & TSS_ERRORS) { // No, mark our subscription as bad_service // the scheduler will take care of things error = tss2errcode(sm->sm_code); @@ -493,7 +493,7 @@ subscription_input(void *opauqe, streaming_message_t *sm) } if (sm->sm_type == SMT_SERVICE_STATUS && - sm->sm_code & TSS_TIMEOUT) { + sm->sm_code & (TSS_TUNING|TSS_TIMEOUT)) { error = tss2errcode(sm->sm_code); if (error > s->ths_testing_error) s->ths_testing_error = error;