]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
implement TSS_TUNING message for late tuning error notification (SAT>IP)
authorJaroslav Kysela <perex@perex.cz>
Fri, 12 Dec 2014 10:19:26 +0000 (11:19 +0100)
committerJaroslav Kysela <perex@perex.cz>
Fri, 12 Dec 2014 10:19:26 +0000 (11:19 +0100)
src/dvr/dvr_rec.c
src/htsp_server.c
src/input/mpegts.h
src/input/mpegts/mpegts_input.c
src/input/mpegts/mpegts_mux.c
src/input/mpegts/satip/satip_frontend.c
src/service.c
src/service.h
src/service_mapper.c
src/subscriptions.c

index 950fe8aafd28a66cafa46090f1ac48906605888c..71631b65734ca835a2daa5272c027c351c0fa5c2 100644 (file)
@@ -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;
 
index 69558f73a5da1ce1282eb161f9612844b53a49ac..d7b2e0e948806a32905975bf884cab37f0ca1c19 100644 (file)
@@ -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));
   }
 }
index c5ea0148e292934f5fb6fc745aa2f7c9cef785b9..2a000fa014462c129cc96e93fd90165b76d4b741 100644 (file)
@@ -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 );
index 6896a0e7f13ba48e9e042ecf53315b6b29c600d1..33e808562908a473060c5026a6b4ae033db9862d 100644 (file)
@@ -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;
index 246ae15b5fa1fc41a3c44a50332e85ae83d92ba0..ba11b0447d0b7bec0c36c1825ba69c55d516352f 100644 (file)
@@ -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)
index d15471319a6eba2dcccbcbfe1fcc0cd2f775722f..b910b58e2677e59298f93e7a7be7623c361c7bb8 100644 (file)
@@ -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;
index 5897d23be4ccd61d4b8a97f77436b68c8580ef92..b6bf458272e3baa560ebec45199ca90506eb1839 100644 (file)
@@ -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;
 
index d4f4664cee2f6c277b1f5c038ccf669c00a1eaee..fb8b38f2e3fdfce5a6a302ae3a5ba26d2e6fa503 100644 (file)
@@ -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
 
index dafe1591d580ebc04f3ba7745f424577a82d9512..777da9ec85a71c622b74d8b545d060146ab178d9 100644 (file)
@@ -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);
         }
index 150d4d14631570f935c517f95a63e94670f95a13..1c0a08b1312bee2d3624e60d93812404949949ba 100644 (file)
@@ -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;