]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
SAT>IP Server: fixed issues for the Elgato SAT>IP Android app
authorJaroslav Kysela <perex@perex.cz>
Fri, 13 Mar 2015 22:59:31 +0000 (23:59 +0100)
committerJaroslav Kysela <perex@perex.cz>
Fri, 13 Mar 2015 22:59:31 +0000 (23:59 +0100)
src/http.c
src/satip/rtp.c
src/satip/rtsp.c
src/satip/server.c

index 9f1f8cca3fcb789dee94f9480f552a458342e219..ec0bbecd28f27da4319a3939cfe8ca7eff033ce9 100644 (file)
@@ -949,6 +949,8 @@ http_parse_get_args(http_connection_t *hc, char *args)
 {
   char *k, *v;
 
+  if (args && *args == '&')
+    args++;
   while(args) {
     k = args;
     if((args = strchr(args, '=')) == NULL)
@@ -1008,13 +1010,18 @@ http_serve_requests(http_connection_t *hc)
         goto error;
 
       if(!*hdrline)
-             break; /* header complete */
-
-      if((n = http_tokenize(hdrline, argv, 2, -1)) < 2)
-             continue;
-
-      if((c = strrchr(argv[0], ':')) == NULL)
-             goto error;
+        break; /* header complete */
+
+      if((n = http_tokenize(hdrline, argv, 2, -1)) < 2) {
+        if ((c = strchr(hdrline, ':')) != NULL) {
+          *c = '\0';
+          argv[0] = hdrline;
+          argv[1] = c + 1;
+        } else {
+          continue;
+        }
+      } else if((c = strrchr(argv[0], ':')) == NULL)
+        goto error;
 
       *c = 0;
       http_arg_set(&hc->hc_args, argv[0], argv[1]);
index ef372578dbb4b7f725940edf33c437713e7b3283..d1c39fd2b183225ece3e775967d7455634e463f2 100644 (file)
@@ -48,6 +48,7 @@ typedef struct satip_rtp_session {
   int um_packet;
   uint16_t seq;
   signal_status_t sig;
+  int sig_lock;
   pthread_mutex_t lock;
 } satip_rtp_session_t;
 
@@ -114,6 +115,8 @@ satip_rtp_loop(satip_rtp_session_t *rtp, uint8_t *data, int len)
   struct iovec *v = rtp->um_iovec + rtp->um_packet;
 
   assert((len % 188) == 0);
+  if (len > 0)
+    rtp->sig_lock = 1;
   for ( ; len >= 188 ; data += 188, len -= 188) {
     pid = ((data[1] & 0x1f) << 8) | data[2];
     if (pid != last_pid && !rtp->pids.all) {
@@ -372,8 +375,7 @@ satip_status_build(satip_rtp_session_t *rtp, char *buf, int len)
   const char *bw, *tmode, *gi, *plp, *t2id, *sm, *c2tft, *ds, *specinv;
   int i, j, r, level = 0, lock = 0, quality = 0;
 
-  if (rtp->sig.snr > 0)
-    lock = 1;
+  lock = rtp->sig_lock;
   switch (rtp->sig.signal_scale) {
   case SIGNAL_STATUS_SCALE_RELATIVE:
     level = MIN(240, MAX(0, (rtp->sig.signal * 245) / 0xffff));
@@ -382,6 +384,7 @@ satip_status_build(satip_rtp_session_t *rtp, char *buf, int len)
     level = MIN(240, MAX(0, (rtp->sig.signal + 90000) / 375));
     break;
   default:
+    level = lock ? 10 : 0;
     break;
   }
   switch (rtp->sig.snr_scale) {
@@ -392,6 +395,7 @@ satip_status_build(satip_rtp_session_t *rtp, char *buf, int len)
     quality = MIN(15, MAX(0, (rtp->sig.snr / 2000)));
     break;
   default:
+    quality = lock ? 1 : 0;
     break;
   }
 
index 390b0773de315770de54fef7a4d23b3a034ce826..f57df44dbdd823a2d762a2dd2a9ac18b19c99d2b 100644 (file)
@@ -300,6 +300,10 @@ rtsp_clean(session_t *rs)
 {
   slave_subscription_t *sub;
 
+  if (rs->run) {
+    satip_rtp_close((void *)(intptr_t)rs->stream);
+    rs->run = 0;
+  }
   if (rs->subs) {
     while ((sub = LIST_FIRST(&rs->slaves)) != NULL)
       rtsp_slave_remove(rs, (mpegts_service_t *)rs->subs->ths_service,
@@ -321,6 +325,7 @@ rtsp_clean(session_t *rs)
 static int
 rtsp_validate_service(mpegts_service_t *s)
 {
+  int av = 0, enc = 0;
   elementary_stream_t *st;
 
   pthread_mutex_lock(&s->s_stream_mutex);
@@ -328,12 +333,15 @@ rtsp_validate_service(mpegts_service_t *s)
     pthread_mutex_unlock(&s->s_stream_mutex);
     return 0;
   }
-  TAILQ_FOREACH(st, &s->s_components, es_link)
+  TAILQ_FOREACH(st, &s->s_components, es_link) {
+    if (st->es_type == SCT_CA)
+      enc = 1;
     if (st->es_pid > 0 &&
         (SCT_ISVIDEO(st->es_type) || SCT_ISAUDIO(st->es_type)))
-      break;
+      av = 1;
+    }
   pthread_mutex_unlock(&s->s_stream_mutex);
-  return st != NULL;
+  return enc && av;
 }
 
 /*
@@ -398,7 +406,8 @@ end:
  */
 static int
 rtsp_start
-  (http_connection_t *hc, session_t *rs, char *addrbuf, int newmux, int setup)
+  (http_connection_t *hc, session_t *rs, char *addrbuf,
+   int newmux, int setup, int oldrun)
 {
   mpegts_network_t *mn, *mn2;
   dvb_network_t *ln;
@@ -422,22 +431,24 @@ rtsp_start
       }
     }
     if (mux == NULL && mn2) {
+      dvb_mux_conf_str(&rs->dmc, buf, sizeof(buf));
+      tvhwarn("satips", "%i/%s/%i: create mux %s",
+              rs->frontend, rs->session, rs->stream, buf);
       mux = (dvb_mux_t *)
         mn2->mn_create_mux(mn2, (void *)(intptr_t)rs->nsession,
                            MPEGTS_ONID_NONE, MPEGTS_TSID_NONE,
-                           &rs->dmc, 0);
+                           &rs->dmc, 1);
       if (mux)
         created = 1;
     }
     if (mux == NULL) {
       dvb_mux_conf_str(&rs->dmc, buf, sizeof(buf));
-      tvhwarn("satips", "%i: unable to create mux %s", rs->frontend, buf);
+      tvhwarn("satips", "%i/%s/%i: unable to create mux %s",
+              rs->frontend, rs->session, rs->stream, buf);
       goto endclean;
     }
     if (rs->mux == mux)
       goto pids;
-    if (rs->run)
-      satip_rtp_close((void *)(intptr_t)rs->stream);
     rtsp_clean(rs);
     rs->mux = mux;
     rs->mux_created = created;
@@ -452,9 +463,9 @@ rtsp_start
                                    http_arg_get(&hc->hc_args, "User-Agent"),
                                    NULL);
     if (!rs->subs)
-      goto endrtp;
-    if (rs->run) {
-      /* restart streaming */
+      goto endclean;
+    /* retrigger play when new setup arrived */
+    if (oldrun) {
       setup = 0;
       rs->run = 0;
     }
@@ -466,7 +477,7 @@ pids:
   }
   if (!setup && !rs->run) {
     if (rs->mux == NULL)
-      goto endrtp;
+      goto endclean;
     satip_rtp_queue((void *)(intptr_t)rs->stream,
                     rs->subs, &rs->prch.prch_sq,
                     hc->hc_peer, rs->rtp_peer_port,
@@ -481,9 +492,6 @@ pids:
   pthread_mutex_unlock(&global_lock);
   return 0;
 
-endrtp:
-  satip_rtp_close((void *)(intptr_t)rs->stream);
-  rs->run = 0;
 endclean:
   rtsp_clean(rs);
   pthread_mutex_unlock(&global_lock);
@@ -598,7 +606,7 @@ rtsp_process_describe(http_connection_t *hc)
   session_t *rs;
   htsbuf_queue_t q;
   char buf[96];
-  int stream;
+  int stream, first = 1;
 
   htsbuf_queue_init(&q, 0);
 
@@ -614,27 +622,30 @@ rtsp_process_describe(http_connection_t *hc)
   if (TAILQ_FIRST(&hc->hc_req_args))
     goto error;
 
-  if (hc->hc_session) {
-    pthread_mutex_lock(&rtsp_lock);
-    TAILQ_FOREACH(rs, &rtsp_sessions, link)
-      if (rs->stream == stream)
-        break;
-    if (rs) {
-      rtsp_describe_header(rs, &q);
-      rtsp_describe_session(rs, &q);
+  pthread_mutex_lock(&rtsp_lock);
+  TAILQ_FOREACH(rs, &rtsp_sessions, link) {
+    if (hc->hc_session) {
+      if (strcmp(hc->hc_session, rs->session))
+        continue;
+      if (stream > 0 && rs->stream != stream)
+        continue;
     }
-    pthread_mutex_unlock(&rtsp_lock);
-    if (rs == NULL) {
+    if (first) {
+      rtsp_describe_header(hc->hc_session ? rs : NULL, &q);
+      first = 0;
+    }
+    rtsp_describe_session(rs, &q);
+  }
+  pthread_mutex_unlock(&rtsp_lock);
+
+  if (first) {
+    if (hc->hc_session) {
       http_error(hc, HTTP_STATUS_BAD_SESSION);
       return 0;
     }
-  } else {
-    pthread_mutex_lock(&rtsp_lock);
     rtsp_describe_header(NULL, &q);
-    TAILQ_FOREACH(rs, &rtsp_sessions, link)
-      rtsp_describe_session(rs, &q);
-    pthread_mutex_unlock(&rtsp_lock);
   }
+
   http_arg_init(&args);
   if (hc->hc_session)
     http_arg_set(&args, "Session", hc->hc_session);
@@ -875,7 +886,7 @@ static int
 rtsp_process_play(http_connection_t *hc, int setup)
 {
   session_t *rs;
-  int errcode = HTTP_STATUS_BAD_REQUEST, r, findex = 0, valid;
+  int errcode = HTTP_STATUS_BAD_REQUEST, r, findex = 0, valid, oldrun = 0;
   int stream, delsys = DVB_SYS_NONE, msys, fe, src, freq, pol, sr;
   int fec, ro, plts, bw, tmode, mtype, gi, plp, t2id, sm, c2tft, ds, specinv;
   char *u, *s;
@@ -922,19 +933,22 @@ rtsp_process_play(http_connection_t *hc, int setup)
     delsys = rtsp_delsys(fe, &findex);
     if (delsys == DVB_SYS_NONE)
       goto error;
+  } else {
+    delsys = msys;
   }
 
   if (setup) {
     if (delsys == DVB_SYS_NONE) goto error;
     if (msys == DVB_SYS_NONE) goto error;
-    if (!fe) goto error;
     if (!valid) goto error;
     if (!rs)
       rs = rtsp_new_session(msys, 0, -1);
     else if (stream != rs->stream)
       rs = rtsp_new_session(msys, rs->nsession, stream);
-    else
+    else {
+      oldrun = rs->run;
       rtsp_close_session(rs);
+    }
     r = parse_transport(hc);
     if (r < 0) {
       errcode = HTTP_STATUS_BAD_TRANSFER;
@@ -944,7 +958,7 @@ rtsp_process_play(http_connection_t *hc, int setup)
       errcode = HTTP_STATUS_METHOD_INVALID;
       goto error;
     }
-    rs->frontend = fe;
+    rs->frontend = fe > 0 ? fe : 1;
     rs->rtp_peer_port = r;
     dmc = &rs->dmc;
   } else {
@@ -953,6 +967,7 @@ rtsp_process_play(http_connection_t *hc, int setup)
         errcode = HTTP_STATUS_NOT_FOUND;
       goto error;
     }
+    oldrun = rs->run;
     dmc = &rs->dmc;
     if (rs->mux == NULL) goto error;
     if (!fe) {
@@ -1106,13 +1121,13 @@ play:
     mpegts_pid_del_group(&rs->pids, &delpids);
   if (addpids.count > 0)
     mpegts_pid_add_group(&rs->pids, &addpids);
-  if ((r = rtsp_start(hc, rs, addrbuf, valid, setup)) < 0) {
+  if ((r = rtsp_start(hc, rs, addrbuf, valid, setup, oldrun)) < 0) {
     errcode = r;
     goto error;
   }
 
   if (setup)
-    tvhdebug("satips", "%i/%s/%d: setup from %s:%d, RTP: %d, RTCP: %d, pids ",
+    tvhdebug("satips", "%i/%s/%d: setup from %s:%d, RTP: %d, RTCP: %d",
              rs->frontend, rs->session, rs->stream,
              addrbuf, IP_PORT(*hc->hc_peer),
              rs->rtp_peer_port, rs->rtp_peer_port + 1);
index 24d96bed36c9e29fc1fe39ecd071932943182b46..150c11bcfa398897197f7d669d192c226e074c10 100644 (file)
@@ -60,11 +60,10 @@ satip_server_http_xml(http_connection_t *hc)
 <manufacturerURL>http://tvheadend.org</manufacturerURL>\n\
 <modelDescription>TVHeadend %s</modelDescription>\n\
 <modelName>TVHeadend SAT>IP</modelName>\n\
-<modelNumber>1</modelNumber>\n\
-<modelURL>http://tvheadend.org</modelURL>\n\
+<modelNumber>1.0</modelNumber>\n\
+<modelURL></modelURL>\n\
 <serialNumber>123456</serialNumber>\n\
 <UDN>uuid:%s</UDN>\n\
-<UPC>TVHeadend %s</UPC>\n\
 <iconList>\n\
 <icon>\n\
 <mimetype>image/png</mimetype>\n\
@@ -74,7 +73,7 @@ satip_server_http_xml(http_connection_t *hc)
 <url>http://%s:%d/static/satip-icon40.png</url>\n\
 </icon>\n\
 <icon>\n\
-<mimetype>image/jpg</mimetype>\n\
+<mimetype>image/jpeg</mimetype>\n\
 <width>40</width>\n\
 <height>40</height>\n\
 <depth>16</depth>\n\
@@ -88,7 +87,7 @@ satip_server_http_xml(http_connection_t *hc)
 <url>http://%s:%d/static/satip-icon120.png</url>\n\
 </icon>\n\
 <icon>\n\
-<mimetype>image/jpg</mimetype>\n\
+<mimetype>image/jpeg</mimetype>\n\
 <width>120</width>\n\
 <height>120</height>\n\
 <depth>16</depth>\n\
@@ -100,7 +99,7 @@ satip_server_http_xml(http_connection_t *hc)
 </device>\n\
 </root>\n"
 
-  char buf[sizeof(MSG) + 1024], buf2[16];
+  char buf[sizeof(MSG) + 1024], buf2[64];
   char *devicelist = NULL;
   htsbuf_queue_t q;
   mpegts_network_t *mn;
@@ -122,18 +121,18 @@ satip_server_http_xml(http_connection_t *hc)
     } else if (idnode_is_instance(&mn->mn_id, &dvb_network_dvbc_class))
       dvbc++;
   }
-  if (dvbt && (i = config_get_int("satip_dvbt", 0)) > 0) {
-    htsbuf_qprintf(&q, "DVBT-%d", i);
-    delim++;
-  } else {
-    dvbt = 0;
-  }
   if (dvbs && (i = config_get_int("satip_dvbs", 0)) > 0) {
     htsbuf_qprintf(&q, "%sDVBS2-%d", delim ? "," : "", i);
     delim++;
   } else {
     dvbs = 0;
   }
+  if (dvbt && (i = config_get_int("satip_dvbt", 0)) > 0) {
+    htsbuf_qprintf(&q, "%sDVBT-%d", delim ? "," : "", i);
+    delim++;
+  } else {
+    dvbt = 0;
+  }
   if (dvbc && (i = config_get_int("satip_dvbc", 0)) > 0) {
     htsbuf_qprintf(&q, "%sDVBC-%d", delim ? "," : "", i);
     delim++;
@@ -153,13 +152,14 @@ satip_server_http_xml(http_connection_t *hc)
             buf, dvbt + dvbs + dvbc ? "tuner settings - global config" : "network assignment");
   }
 
-  buf2[0] = '\0';
   if (satip_server_rtsp_port != 554)
-    snprintf(buf2, sizeof(buf2), ":%d", satip_server_rtsp_port);
+    snprintf(buf2, sizeof(buf2), ":%d %s", satip_server_rtsp_port, satip_server_uuid + 26);
+  else
+    snprintf(buf2, sizeof(buf2), " %s", satip_server_uuid + 26);
 
   snprintf(buf, sizeof(buf), MSG,
            buf2, tvheadend_version,
-           satip_server_uuid, tvheadend_version,
+           satip_server_uuid,
            http_server_ip, http_server_port,
            http_server_ip, http_server_port,
            http_server_ip, http_server_port,
@@ -170,8 +170,10 @@ satip_server_http_xml(http_connection_t *hc)
   free(devicelist);
 
   http_arg_init(&args);
-  snprintf(buf2, sizeof(buf2), "%d", satip_server_rtsp_port);
-  http_arg_set(&args, "X-SATIP-RTSP-Port", buf2);
+  if (satip_server_rtsp_port != 554) {
+    snprintf(buf2, sizeof(buf2), "%d", satip_server_rtsp_port);
+    http_arg_set(&args, "X-SATIP-RTSP-Port", buf2);
+  }
   if (srcs) {
     snprintf(buf2, sizeof(buf2), "%d", srcs);
     http_arg_set(&args, "X-SATIP-Sources", buf2);
@@ -405,9 +407,9 @@ satips_upnp_discovery_received
     if (http_tokenize(ptr, argv, 2, ':') == 2) {
       if (strcmp(argv[0], "ST") == 0)
         st = argv[1];
-      else if (strcmp(argv[0], "HOST") == 0)
+      else if (strcasecmp(argv[0], "HOST") == 0)
         host = argv[1];
-      else if (strcmp(argv[0], "MAN") == 0)
+      else if (strcasecmp(argv[0], "MAN") == 0)
         man = argv[1];
       else if (strcmp(argv[0], "DEVICEID.SES.COM") == 0)
         deviceid = argv[1];