]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
SAT>IP Server: improve PID handling (using new fcn set)
authorJaroslav Kysela <perex@perex.cz>
Wed, 4 Mar 2015 09:27:09 +0000 (10:27 +0100)
committerJaroslav Kysela <perex@perex.cz>
Wed, 11 Mar 2015 20:41:13 +0000 (21:41 +0100)
Makefile
src/input/mpegts.h
src/input/mpegts/mpegts_pid.c [new file with mode: 0644]
src/satip/rtp.c
src/satip/rtsp.c
src/satip/server.h

index 3e9e6a52aa9e3d0b4aa89a8f6e79091053f53f0c..fb4549257220f57fb1f37db627b2c598c18d9e3f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -230,6 +230,7 @@ SRCS-$(CONFIG_MPEGTS) += \
        src/descrambler/descrambler.c \
        src/descrambler/caclient.c \
        src/input/mpegts.c \
+       src/input/mpegts/mpegts_pid.c \
        src/input/mpegts/mpegts_input.c \
        src/input/mpegts/mpegts_network.c \
        src/input/mpegts/mpegts_mux.c \
index bf402e555979c27755a03419dd87c8bd767fceb3..37d51c1c319e9f4b5b5cc02dc40b0dc030f18870 100644 (file)
@@ -37,6 +37,8 @@
 #define MPEGTS_PID_NONE         0xFFFF
 
 /* Types */
+typedef int16_t                     mpegts_apid_t;
+typedef struct mpegts_apids         mpegts_apids_t;
 typedef struct mpegts_table         mpegts_table_t;
 typedef struct mpegts_psi_section   mpegts_psi_section_t;
 typedef struct mpegts_network       mpegts_network_t;
@@ -73,6 +75,31 @@ void mpegts_init ( int linuxdvb_mask, str_list_t *satip_client,
                    str_list_t *tsfiles, int tstuners );
 void mpegts_done ( void );
 
+/* **************************************************************************
+ * PIDs
+ * *************************************************************************/
+
+struct mpegts_apids {
+  mpegts_apid_t *pids;
+  int alloc;
+  int count;
+  int all;
+};
+
+int mpegts_pid_init ( mpegts_apids_t *pids, mpegts_apid_t *vals, int count );
+void mpegts_pid_done ( mpegts_apids_t *pids );
+void mpegts_pid_reset ( mpegts_apids_t *pids );
+int mpegts_pid_add ( mpegts_apids_t *pids, mpegts_apid_t pid );
+int mpegts_pid_add_group ( mpegts_apids_t *pids, mpegts_apids_t *vals );
+int mpegts_pid_del ( mpegts_apids_t *pids, mpegts_apid_t pid );
+int mpegts_pid_del_group ( mpegts_apids_t *pids, mpegts_apids_t *vals );
+int mpegts_pid_find_index ( mpegts_apids_t *pids, mpegts_apid_t pid );
+static inline int mpegts_pid_exists ( mpegts_apids_t *pids, mpegts_apid_t pid )
+  { return pids->all || mpegts_pid_find_index(pids, pid) >= 0; }
+int mpegts_pid_copy ( mpegts_apids_t *dst, mpegts_apids_t *src );
+int mpegts_pid_compare ( mpegts_apids_t *dst, mpegts_apids_t *src,
+                         mpegts_apids_t *add, mpegts_apids_t *del );
+
 /* **************************************************************************
  * Data / SI processing
  * *************************************************************************/
@@ -920,6 +947,7 @@ static inline mpegts_service_t *mpegts_service_find_by_uuid(const char *uuid)
 
 void mpegts_service_delete ( service_t *s, int delconf );
 
+
 /*
  * MPEG-TS event handler
  */
diff --git a/src/input/mpegts/mpegts_pid.c b/src/input/mpegts/mpegts_pid.c
new file mode 100644 (file)
index 0000000..ede0a80
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ *  MPEGTS PID list management
+ *  Copyright (C) 2015 Jaroslav Kysela
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "tvheadend.h"
+#include "input.h"
+
+int
+mpegts_pid_init(mpegts_apids_t *pids, mpegts_apid_t *vals, int count)
+{
+  int alloc = count + 32;
+  mpegts_apid_t *p = calloc(alloc, sizeof(*pids));
+
+  if (p == NULL)
+    return -1;
+  pids->pids = p;
+  pids->alloc = alloc;
+  pids->all = 0;
+  if (vals) {
+    memcpy(p, vals, count * sizeof(*pids));
+    pids->count = count;
+  }
+  return 0;
+}
+
+void
+mpegts_pid_done(mpegts_apids_t *pids)
+{
+  free(pids->pids);
+  pids->pids = NULL;
+  pids->alloc = pids->count = 0;
+}
+
+void
+mpegts_pid_reset(mpegts_apids_t *pids)
+{
+  pids->alloc = pids->count = 0;
+}
+
+int
+mpegts_pid_add(mpegts_apids_t *pids, mpegts_apid_t pid)
+{
+  mpegts_apid_t *p;
+  int i;
+
+  assert(pids);
+  assert(pid >= 0 && pid <= 8191);
+  if (pids->alloc == pids->count) {
+    i = pids->alloc + 32;
+    p = realloc(pids->pids, i * sizeof(*p));
+    if (p == NULL)
+      return -1;
+    pids->pids = p;
+    pids->alloc = i;
+  }
+  p = pids->pids;
+  for (i = pids->count++; i > 0 && p[i - 1] > pid; i--)
+    p[i] = p[i - 1];
+  p[i] = pid;
+  return 0;
+}
+
+int
+mpegts_pid_add_group(mpegts_apids_t *pids, mpegts_apids_t *vals)
+{
+  int i, r;
+
+  for (i = 0; i < vals->count; i++) {
+    r = mpegts_pid_add(pids, vals->pids[i]);
+    if (r)
+      return r;
+  }
+  return 0;
+}
+
+int
+mpegts_pid_find_index(mpegts_apids_t *pids, mpegts_apid_t pid)
+{
+  mpegts_apid_t *p = pids->pids;
+  int first = 0, last = pids->count - 1, i;
+  for (i = last / 2; first <= last; i = (first + last) / 2) {
+    if (p[i] < pid)
+      first = i + 1;
+    else if (p[i] == pid)
+      return i;
+    else
+      last = i - 1;
+  }
+  return -1;
+}
+
+int
+mpegts_pid_del(mpegts_apids_t *pids, mpegts_apid_t pid)
+{
+  int i;
+
+  assert(pids);
+  assert(pid >= 0 && pid <= 8191);
+  if ((i = mpegts_pid_find_index(pids, pid)) >= 0) {
+    memmove(&pids->pids[i], &pids->pids[i+1],
+            (pids->count - i - 1) * sizeof(mpegts_apid_t));
+    pids->count--;
+    return 0;
+  } else {
+    return -1;
+  }
+}
+
+int
+mpegts_pid_del_group(mpegts_apids_t *pids, mpegts_apids_t *vals)
+{
+  int i, r;
+
+  for (i = 0; i < vals->count; i++) {
+    r = mpegts_pid_del(pids, vals->pids[i]);
+    if (r)
+      return r;
+  }
+  return 0;
+}
+
+int
+mpegts_pid_copy(mpegts_apids_t *dst, mpegts_apids_t *src)
+{
+  mpegts_apid_t *p;
+  int i;
+
+  if (dst->alloc < src->alloc) {
+    i = src->alloc;
+    p = realloc(dst->pids, i * sizeof(*p));
+    if (p == NULL)
+      return -1;
+    dst->pids = p;
+    dst->alloc = i;
+  }
+  dst->count = src->count;
+  dst->all = src->all;
+  memcpy(dst->pids, src->pids, src->count * sizeof(mpegts_apid_t));
+  return 0;
+}
+
+int
+mpegts_pid_compare(mpegts_apids_t *dst, mpegts_apids_t *src,
+                   mpegts_apids_t *add, mpegts_apids_t *del)
+{
+  int i;
+
+  if (mpegts_pid_init(add, NULL, 0) ||
+      mpegts_pid_init(del, NULL, 0))
+    return -1;
+  for (i = 0; i < src->count; i++)
+    if (mpegts_pid_find_index(dst, src->pids[i]) < 0)
+      mpegts_pid_add(del, src->pids[i]);
+  for (i = 0; i < dst->count; i++)
+    if (mpegts_pid_find_index(src, dst->pids[i]) < 0)
+      mpegts_pid_add(add, dst->pids[i]);
+  return add->count || del->count;
+}
index 6c0d895b8205807e08dd614b49883f28089e59ca..1eb4d3814082876b01b1a0ebd9d3c817564a6161 100644 (file)
@@ -41,7 +41,7 @@ typedef struct satip_rtp_session {
   int frontend;
   int source;
   dvb_mux_conf_t dmc;
-  int16_t pids[RTSP_PIDS];
+  mpegts_apids_t pids;
   udp_multisend_t um;
   struct iovec *um_iovec;
   int um_packet;
@@ -109,15 +109,18 @@ static int
 satip_rtp_loop(satip_rtp_session_t *rtp, uint8_t *data, int len)
 {
   int i, j, pid, last_pid = -1, r;
-  int16_t *pids = rtp->pids;
+  mpegts_apid_t *pids = rtp->pids.pids;
   struct iovec *v = rtp->um_iovec + rtp->um_packet;
 
   assert((len % 188) == 0);
   for ( ; len >= 188 ; data += 188, len -= 188) {
     pid = ((data[1] & 0x1f) << 8) | data[2];
-    if (pid != last_pid) {
-      for (i = 0, j = -1; i < RTSP_PIDS && (j = pids[i]) >= 0; i++)
+    if (pid != last_pid && !rtp->pids.all) {
+      for (i = 0; i < rtp->pids.count; i++) {
+        j = pids[i];
+        if (pid < j) break;
         if (j == pid) goto found;
+      }
       continue;
 found:
       last_pid = pid;
@@ -238,7 +241,7 @@ void satip_rtp_queue(void *id, th_subscription_t *subs,
                      struct sockaddr_storage *peer, int port,
                      int fd_rtp, int fd_rtcp,
                      int frontend, int source, dvb_mux_conf_t *dmc,
-                     int16_t *pids)
+                     mpegts_apids_t *pids)
 {
   satip_rtp_session_t *rtp = calloc(1, sizeof(*rtp));
 
@@ -254,7 +257,8 @@ void satip_rtp_queue(void *id, th_subscription_t *subs,
   rtp->fd_rtcp = fd_rtcp;
   rtp->subs = subs;
   rtp->sq = sq;
-  memcpy(rtp->pids, pids, sizeof(*pids)*RTSP_PIDS);
+  mpegts_pid_init(&rtp->pids, NULL, pids->count);
+  mpegts_pid_copy(&rtp->pids, pids);
   udp_multisend_init(&rtp->um, RTP_PACKETS, RTP_PAYLOAD, &rtp->um_iovec);
   satip_rtp_header(rtp);
   rtp->frontend = frontend;
@@ -268,7 +272,7 @@ void satip_rtp_queue(void *id, th_subscription_t *subs,
   pthread_mutex_unlock(&satip_rtp_lock);
 }
 
-void satip_rtp_update_pids(void *id, int16_t *pids)
+void satip_rtp_update_pids(void *id, mpegts_apids_t *pids)
 {
   satip_rtp_session_t *rtp;
 
@@ -276,7 +280,7 @@ void satip_rtp_update_pids(void *id, int16_t *pids)
   rtp = satip_rtp_find(id);
   if (rtp) {
     pthread_mutex_lock(&rtp->lock);
-    memcpy(rtp->pids, pids, sizeof(*pids)*RTSP_PIDS);
+    mpegts_pid_copy(&rtp->pids, pids);
     pthread_mutex_unlock(&rtp->lock);
   }
   pthread_mutex_unlock(&satip_rtp_lock);
@@ -299,6 +303,7 @@ void satip_rtp_close(void *id)
     pthread_mutex_unlock(&satip_rtp_lock);
     pthread_join(rtp->tid, NULL);
     udp_multisend_free(&rtp->um);
+    mpegts_pid_done(&rtp->pids);
     free(rtp);
   } else {
     pthread_mutex_unlock(&satip_rtp_lock);
@@ -365,8 +370,8 @@ satip_rtcp_build(satip_rtp_session_t *rtp, uint8_t *msg)
   }
 
   pids[0] = 0;
-  for (i = len = 0; i < RTSP_PIDS && rtp->pids[i] >= 0; i++)
-    len += snprintf(pids + len, sizeof(pids) - len, "%d,", rtp->pids[i]);
+  for (i = len = 0; i < rtp->pids.count; i++)
+    len += snprintf(pids + len, sizeof(pids) - len, "%d,", rtp->pids.pids[i]);
   if (len && pids[len-1] == ',')
     pids[len-1] = '\0';
 
index 6bae9edd1ab15fca99d8d781410a6e252d3314c1..04a987ea76add3c0152db351b18cb6354b1a17c2 100644 (file)
@@ -40,7 +40,7 @@ typedef struct session {
   uint32_t nsession;
   char session[9];
   dvb_mux_conf_t dmc;
-  int16_t pids[RTSP_PIDS];
+  mpegts_apids_t pids;
   gtimer_t timer;
   dvb_mux_t *mux;
   int mux_created;
@@ -106,7 +106,6 @@ static struct session *
 rtsp_new_session(int delsys, uint32_t nsession, int session)
 {
   struct session *rs = calloc(1, sizeof(*rs));
-  int i;
 
   if (rs == NULL)
     return NULL;
@@ -118,8 +117,7 @@ rtsp_new_session(int delsys, uint32_t nsession, int session)
     if (session_number == 0)
       session_number += 9876;
   }
-  for (i = 0; i < RTSP_PIDS; i++)
-    rs->pids[i] = -1;
+  mpegts_pid_init(&rs->pids, NULL, 0);
   TAILQ_INSERT_TAIL(&rtsp_sessions, rs, link);
   return rs;
 }
@@ -221,69 +219,6 @@ rtsp_parse_args(http_connection_t *hc, char *u)
   return stream;
 }
 
-/*
- *
- */
-static void
-rtsp_clrpids(session_t *rs)
-{
-  int16_t *pids = rs->pids;
-  int i = RTSP_PIDS;
-  while (*pids >= 0 && i-- > 0)
-    *pids++ = -1;
-}
-
-/*
- *
- */
-static int
-rtsp_addpids(session_t *rs, int16_t *pids)
-{
-  int pid, i, j;
-
-  while ((pid = *pids++) >= 0) {
-    for (i = 0; i < RTSP_PIDS; i++) {
-      if (rs->pids[i] > pid) {
-        if (rs->pids[RTSP_PIDS-1] >= 0)
-          return -1;
-        for (j = RTSP_PIDS-1; j != i; j--)
-          rs->pids[j] = rs->pids[j-1];
-        rs->pids[i] = pid;
-        break;
-      } else if (rs->pids[i] == pid) {
-        break;
-      } else if (rs->pids[i] < 0) {
-        rs->pids[i] = pid;
-        break;
-      }
-    }
-  }
-  return 0;
-}
-
-/*
- *
- */
-static int
-rtsp_delpids(session_t *rs, int16_t *pids)
-{
-  int pid, i, j;
-  
-  while ((pid = *pids++) >= 0) {
-    for (i = 0; i < RTSP_PIDS; i++) {
-      if (rs->pids[i] > pid)
-        break;
-      else if (rs->pids[i] == pid) {
-        for (j = i; rs->pids[j] >= 0 && j + 1 < RTSP_PIDS; j++)
-          rs->pids[j] = rs->pids[j+1];
-        rs->pids[RTSP_PIDS-1] = -1;
-        break;
-      }
-    }
-  }
-  return 0;
-}
-
 /*
  *
  */
@@ -368,7 +303,7 @@ rtsp_start
     }
   } else {
 pids:
-    satip_rtp_update_pids((void *)(intptr_t)rs->stream, rs->pids);
+    satip_rtp_update_pids((void *)(intptr_t)rs->stream, &rs->pids);
   }
   if (!setup && !rs->run) {
     if (rs->mux == NULL)
@@ -377,7 +312,8 @@ pids:
                     rs->subs, &rs->prch.prch_sq,
                     hc->hc_peer, rs->rtp_peer_port,
                     rs->udp_rtp->fd, rs->udp_rtcp->fd,
-                    rs->frontend, rs->findex, &rs->mux->lm_tuning, rs->pids);
+                    rs->frontend, rs->findex, &rs->mux->lm_tuning,
+                    &rs->pids);
     rs->run = 1;
   }
   pthread_mutex_unlock(&global_lock);
@@ -597,32 +533,32 @@ gi_to_tvh(http_connection_t *hc)
 }
 
 static int
-parse_pids(char *p, int16_t *pids)
+parse_pids(char *p, mpegts_apids_t *pids)
 {
   char *x, *saveptr;
-  int i = 0;
+  int i = 0, pid;
 
-  if (p == NULL || *p == '\0') {
-    pids[0] = -1;
+  mpegts_pid_reset(pids);
+  if (p == NULL || *p == '\0')
     return 0;
-  }
   x = strtok_r(p, ",", &saveptr);
   while (1) {
     if (x == NULL)
       break;
-    if (i >= RTSP_PIDS)
-      return -1;
-    pids[i] = atoi(x);
-    if (pids[i] < 0 || pids[i] > 8191) {
-      pids[i] = -1;
-      return -1;
+    if (strcmp(x, "all") == 0) {
+      pids->all = 1;
+    } else {
+      pids->all = 0;
+      pid = atoi(x);
+      if (pid < 0 || pid > 8191)
+        return -1;
+      mpegts_pid_add(pids, pid);
     }
     x = strtok_r(NULL, ",", &saveptr);
     i++;
   }
   if (i == 0)
     return -1;
-  pids[i] = -1;
   return 0;
 }
 
@@ -658,11 +594,15 @@ rtsp_process_play(http_connection_t *hc, int setup)
   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;
-  int16_t pids[RTSP_PIDS+1], addpids[RTSP_PIDS+1], delpids[RTSP_PIDS+1];
+  mpegts_apids_t pids, addpids, delpids;
   dvb_mux_conf_t *dmc;
   char buf[256], addrbuf[50];
   http_arg_list_t args;
 
+  mpegts_pid_init(&pids, NULL, 0);
+  mpegts_pid_init(&addpids, NULL, 0);
+  mpegts_pid_init(&delpids, NULL, 0);
+
   http_arg_init(&args);
   tcp_get_ip_str((struct sockaddr*)hc->hc_peer, addrbuf, sizeof(addrbuf));
 
@@ -673,15 +613,15 @@ rtsp_process_play(http_connection_t *hc, int setup)
 
   fe = atoi(http_arg_get_remove(&hc->hc_req_args, "fe"));
   s = http_arg_get_remove(&hc->hc_req_args, "addpids");
-  if (parse_pids(s, addpids)) goto error2;
+  if (parse_pids(s, &addpids)) goto error2;
   s = http_arg_get_remove(&hc->hc_req_args, "delpids");
-  if (parse_pids(s, delpids)) goto error2;
+  if (parse_pids(s, &delpids)) goto error2;
   s = http_arg_get_remove(&hc->hc_req_args, "pids");
-  if (parse_pids(s, pids)) goto error2;
+  if (parse_pids(s, &pids)) goto error2;
   msys = msys_to_tvh(hc);
   freq = atof(http_arg_get_remove(&hc->hc_req_args, "freq")) * 1000000;
 
-  if (addpids[0] >= 0 || delpids[0] >= 0) {
+  if (addpids.count > 0 || delpids.count > 0) {
     if (setup)
       goto error2;
     if (!stream)
@@ -872,14 +812,12 @@ rtsp_process_play(http_connection_t *hc, int setup)
   }
 
 play:
-  if (pids[0] >= 0) {
-    rtsp_clrpids(rs);
-    rtsp_addpids(rs, pids);
-  }
-  if (delpids[0] >= 0)
-    rtsp_delpids(rs, delpids);
-  if (addpids[0] >= 0)
-    rtsp_addpids(rs, addpids);
+  if (pids.count > 0)
+    mpegts_pid_copy(&rs->pids, &pids);
+  if (delpids.count > 0)
+    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, freq >= 10000000, setup)) < 0) {
     errcode = r;
     goto error;
@@ -891,10 +829,9 @@ play:
              rs->rtp_peer_port, rs->rtp_peer_port + 1);
   dvb_mux_conf_str(dmc, buf, sizeof(buf));
   s = buf + strlen(buf);
-  for (r = 0; r < RTSP_PIDS; r++) {
-    if (rs->pids[r] < 0) break;
+  for (r = 0; r < rs->pids.count; r++) {
     s += snprintf(s, sizeof(buf) - (s - buf), "%s%i",
-                  r > 0 ? "," : " pids ", rs->pids[r]);
+                  r > 0 ? "," : " pids ", rs->pids.pids[r]);
   }
   tvhdebug("satips", "%i/%s/%d: %s %s",
            rs->frontend, rs->session, rs->stream,
@@ -916,14 +853,17 @@ play:
 
   pthread_mutex_unlock(&rtsp_lock);
 
-  http_arg_flush(&args);
-  return 0;
+  goto end;
 
 error:
   pthread_mutex_unlock(&rtsp_lock);
 error2:
   http_error(hc, errcode);
+end:
   http_arg_flush(&args);
+  mpegts_pid_done(&pids);
+  mpegts_pid_done(&addpids);
+  mpegts_pid_done(&delpids);
   return 0;
 }
 
index f1a439a81253f06020f6b1dc8cb6af0741d418be..38fcd049766de8bb7e34b18f335c3afd0e4246e7 100644 (file)
 #include "udp.h"
 #include "http.h"
 
-#define RTSP_PIDS 128
-
 void satip_rtp_queue(void *id, th_subscription_t *subs,
                      streaming_queue_t *sq,
                      struct sockaddr_storage *peer, int port,
                      int fd_rtp, int fd_rtcp,
                      int frontend, int source,
                      dvb_mux_conf_t *dmc,
-                     int16_t *pids);
+                     mpegts_apids_t *pids);
 void satip_rtp_update(void *id, th_subscription_t *subs,
                       streaming_queue_t *sq,
                       int frontend, int source,
                       dvb_mux_conf_t *dmc,
-                      int16_t *pids);
-void satip_rtp_update_pids(void *id, int16_t *pids);
+                      mpegts_apids_t *pids);
+void satip_rtp_update_pids(void *id, mpegts_apids_t *pids);
 void satip_rtp_close(void *id);
 
 void satip_rtp_init(void);