[dvblast-devel] patch SAP announcements generated from sdt

markus at selfnet.de markus at selfnet.de
Fri Oct 19 16:22:22 CEST 2012


Hello

we want to get rid of the minisapserver so we wrote an patch for 
dvblast which adds sap announcements. The announcements are generated 
from the Service Description Table (sdt). just add '--sap' to your 
startup parameters and your streams will be announced.

we are looking forward to your feedback/comments. we know that it is 
just a very limited version, but the basic functionality is working fine 
for us (ipv4 + rtp + dvb-s).

in general do you like the idea of integrated announce protocols?


greetings,
Markus & Dirk

---------------------------------------

 From 84b09aae9c427e0b01593567ba837d06d8dfd2c2 Mon Sep 17 00:00:00 2001
 From: Markus Wick <markus at selfnet.de>
Date: Fri, 19 Oct 2012 15:54:12 +0200
Subject: [PATCH] added sap announcements automaticly generated from sdt
  this is a early state, eg ipv6 is missing

---
  Makefile  |    4 +-
  NEWS      |    1 +
  dvblast.1 |    3 +
  dvblast.c |   22 ++++++-
  sap.c     |  197 
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  sap.h     |   38 ++++++++++++
  6 files changed, 261 insertions(+), 4 deletions(-)
  create mode 100644 sap.c
  create mode 100644 sap.h

diff --git a/Makefile b/Makefile
index 336f663..18b2184 100644
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@ endif

  LDLIBS_DVBLAST += -lpthread

-OBJ_DVBLAST = dvblast.o util.o dvb.o udp.o asi.o demux.o output.o 
en50221.o comm.o mrtg-cnt.o
+OBJ_DVBLAST = dvblast.o util.o dvb.o udp.o asi.o demux.o output.o 
en50221.o comm.o mrtg-cnt.o sap.o
  OBJ_DVBLASTCTL = util.o dvblastctl.o

  ifndef V
@@ -43,7 +43,7 @@ all: dvblast dvblastctl

  .PHONY: clean install uninstall dist

-%.o: %.c Makefile config.h dvblast.h en50221.h comm.h asi.h mrtg-cnt.h
+%.o: %.c Makefile config.h dvblast.h en50221.h comm.h asi.h mrtg-cnt.h 
sap.h
  	@echo "CC      $<"
  	$(Q)$(CROSS)$(CC) $(CFLAGS) -c $<

diff --git a/NEWS b/NEWS
index 32b06a5..ec18015 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,7 @@ Changes between 2.2 and 2.3:
    * Fixed ECM pid selection.
    * Added CA device addressing.
    * Added support for remapping ES pids to fixed values.
+  * Added support for SAP announcements generated from SDT.

  Changes between 2.1 and 2.2:
  ----------------------------
diff --git a/dvblast.1 b/dvblast.1
index 51ca109..5d86ea0 100644
--- a/dvblast.1
+++ b/dvblast.1
@@ -164,6 +164,9 @@ Symbole rate
  \fB\-S\fR, \fB\-\-diseqc\fR <diseqc>
  Satellite number for diseqc (0: no diseqc, 1\-4, A or B)
  .TP
+\fB--sap\fR
+announce streams via sdp/sap
+.TP
  \fB\-t\fR, \fB\-\-ttl\fR <ttl>
  Time-To-Live of the multicast stream
  .TP
diff --git a/dvblast.c b/dvblast.c
index 2da2d38..fcfa3fa 100644
--- a/dvblast.c
+++ b/dvblast.c
@@ -48,6 +48,7 @@
  #include <bitstream/ietf/rtp.h>

  #include "mrtg-cnt.h"
+#include "sap.h"

  
/*****************************************************************************
   * Local declarations
@@ -101,6 +102,8 @@ int i_verbose = DEFAULT_VERBOSITY;
  int i_syslog = 0;
  char *psz_syslog_ident = NULL;

+int b_enable_sap = 0;
+
  bool b_enable_emm = false;
  bool b_enable_ecm = false;

@@ -528,6 +531,7 @@ void usage()
      msg_Raw( NULL, "  -q --quiet            be quiet (less verbosity, 
repeat or use number for even quieter)" );
      msg_Raw( NULL, "  -Q --quit-timeout     when locked, quit after 
this delay (in ms), or after the first lock timeout" );
      msg_Raw( NULL, "  -r --remote-socket <remote socket>" );
+    msg_Raw( NULL, "     --sap              announce streams via 
sdp/sap");
      msg_Raw( NULL, "  -V --version          only display the version" 
);
      msg_Raw( NULL, "  -Z --mrtg-file <file> Log input packets and 
errors into mrtg-file" );
      exit(1);
@@ -610,10 +614,12 @@ int main( int i_argc, char **pp_argv )
          { "mrtg-file",       required_argument, NULL, 'Z' },
          { "ca-number",       required_argument, NULL, 'y' },
          { "pidmap",          required_argument, NULL, '0' },
+        { "sap",             no_argument,       &b_enable_sap,  1  },
          { 0, 0, 0, 0 }
      };

-    while ( (c = getopt_long(i_argc, pp_argv, 
"q::c:r:t:o:i:a:n:f:F:R:s:S:k:v:pb:I:m:P:K:G:H:X:O:uwUTL:E:d:D:A:lg:zCWYeM:N:j:J:B:x:Q:hVZ:y:0:", 
long_options, NULL)) != -1 )
+    int option_index = 0;
+    while ( (c = getopt_long(i_argc, pp_argv, 
"q::c:r:t:o:i:a:n:f:F:R:s:S:k:v:pb:I:m:P:K:G:H:X:O:uwUTL:E:d:D:A:lg:zCWYeM:N:j:J:B:x:Q:hVZ:y:0:", 
long_options, &option_index)) != -1 )
      {
          switch ( c )
          {
@@ -909,7 +915,8 @@ int main( int i_argc, char **pp_argv )
          }
          case 'h':
          default:
-            usage();
+            if(!option_index)
+                usage();
          }
      }
      if ( optind < i_argc || pf_Open == NULL )
@@ -1030,6 +1037,9 @@ int main( int i_argc, char **pp_argv )

      config_ReadFile( psz_conf_file );

+    if ( b_enable_sap )
+        sap_Init();
+
      if ( psz_srv_socket != NULL )
          comm_Open();

@@ -1050,6 +1060,11 @@ int main( int i_argc, char **pp_argv )
              config_ReadFile( psz_conf_file );
          }

+        if ( b_enable_sap )
+        {
+            sap_Announce();
+        }
+
          if ( i_quit_timeout && i_quit_timeout <= i_wallclock )
          {
              switch (i_print_type)
@@ -1079,6 +1094,9 @@ int main( int i_argc, char **pp_argv )
      demux_Close();
      free( p_network_name );

+    if ( b_enable_sap )
+        sap_Close();
+
      if ( b_enable_syslog )
          msg_Disconnect();

diff --git a/sap.c b/sap.c
new file mode 100644
index 0000000..d3e8006
--- /dev/null
+++ b/sap.c
@@ -0,0 +1,197 @@
+/*****************************************************************************
+ * sap.c SAP Announcements generated from SDT
+ 
*****************************************************************************
+ * Copyright Tripleplay service 2004,2005,2011
+ *
+ * Author:  Dirk Braunschweiger <dirkmb at selfnet.de>
+ *          Markus Wick         <markus at selfnet.de>
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 
02110-1301, USA.
+ 
*****************************************************************************/
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <sys/types.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+
+#include <bitstream/dvb/si/sdt.h>
+
+#include "dvblast.h"
+#include "sap.h"
+
+// Reporting timer
+#if defined( WIN32 )
+static LARGE_INTEGER sap_time;
+static LARGE_INTEGER sap_inc;
+#else
+static struct timeval sap_time = { 0, 0 };
+#endif
+
+
+int i_sap_handle;
+int i_next_output;
+struct sockaddr_in addr;
+
+void sap_Init(void)
+{
+//    socklen_t i_sockaddr_len = (p_config->i_family == AF_INET) ?
+//                               sizeof(struct sockaddr_in) :
+//                               sizeof(struct sockaddr_in6);
+
+// No IPv6 Support, yet TODO
+
+    i_sap_handle = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
+
+    if ( i_sap_handle < 0 )
+    {
+        msg_Err( NULL, "couldn't create socket (%s)", strerror(errno) 
);
+        return;
+    }
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_addr.s_addr = inet_addr(SAP_IPv4_DEST);
+    addr.sin_port = htons(SAP_IPv4_DPORT);
+    addr.sin_family = AF_INET;
+
+
+    unsigned char ttl = SAP_IPv4_TTL;
+    setsockopt(i_sap_handle, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, 
sizeof(ttl));
+
+    i_next_output = 0;
+}
+
+void sap_Announce(void)
+{
+    // no output, so no announcements
+    if(i_nb_outputs <= 0) return;
+
+    // See if we need to send the announcements
+    struct timeval now, delta, diff;
+    gettimeofday(&now, NULL);
+    if (timercmp(&now, &sap_time, <)) return;
+
+    // Set the timer for next time
+    //
+    // Normally we add the interval to the previous time so that if 
one
+    // dump is a bit late, the next one still occurs at the correct 
time.
+    // However, if there is a long gap (e.g. because the channel has
+    // stopped for some time), then just rebase the timing to the 
current
+    // time.  I've chosen SAP_INTERVAL as the long gap - this is 
arbitary
+    delta.tv_sec = SAP_INTERVAL/i_nb_outputs;
+    delta.tv_usec = SAP_INTERVAL*1000000/i_nb_outputs%1000000;
+
+    timersub(&now, &sap_time, &diff);
+    if (timercmp(&diff,&delta,>)) {
+        msg_Dbg(NULL, "SAP is %ld seconds late - reset timing\n", 
diff.tv_sec);
+        sap_time = now;
+    }
+    timeradd(&sap_time, &delta, &sap_time);
+
+    if(++i_next_output >= i_nb_outputs) i_next_output = 0;
+
+    char host[100] = "";
+    char serv[100] = "";
+    char service_provider[500] = "";
+    char service_name[500] = "";
+
+    // fetch ip / port combo
+    getnameinfo((struct 
sockaddr*)&pp_outputs[i_next_output]->config.connect_addr,
+                sizeof(struct sockaddr_storage), host, 100, serv, 100,
+                NI_NUMERICHOST | NI_NUMERICSERV);
+
+    // Parsing SDT
+    uint8_t *sdt = pp_outputs[i_next_output]->p_sdt_section;
+    if(!sdt) return;
+
+    uint16_t sid = sdt[11]<<8 | sdt[12]; // SID at byte [11,12]
+
+    int j,k;
+    k=0;                                 // provider begins at 20
+    for(j=0; j<sdt[19] && j<499; j++)    // end is stored in sdt[19]
+        if(sdt[j+20] >= 0x20)
+            service_provider[k++] = sdt[j+20];
+    service_provider[k] = 0;
+
+    k=0;                                 // service begins 1 byte 
after provider
+    for(j=0; j<sdt[20+sdt[19]] && j<499; j++)
+        if(sdt[21+sdt[19]+j] >= 0x20)
+            service_name[k++] = sdt[21+sdt[19]+j];
+    service_name[k] = 0;
+
+    char buffer[1500];
+    char *worker = buffer;
+    char *worker_end = buffer+1500;
+
+    // create the sap header
+    worker[0] = 0x20;
+    worker[1] = 0x00;
+    worker[2] = (sid>>8) & 0xff;
+    worker[3] = sid & 0xff;
+    worker+=4;
+
+    worker += snprintf(worker, worker_end-worker, "\x01\x02\x03\x05");
+    worker += snprintf(worker, worker_end-worker, "application/sdp");
+    worker[0] = 0;
+    worker++;
+
+    // and the sdp payload
+    worker += snprintf(worker, worker_end-worker,
+                       "v=0\r\n"
+                       "o=VideoLan 16975 1 IN IP4 
www.videolan.org\r\n"
+                       "s=%s\r\n"
+                       "i=%s\r\n"
+                       
"u=http://www.videolan.org/projects/dvblast.html\r\n"
+                       "c=IN IP4 %s/255\r\n"
+                       "t=0 0\r\n"
+                       "a=tool:dvblast 2.2-sap-patched\r\n"
+                       "a=type:broadcast\r\n"
+                       "a=charset:UTF-8\r\n"
+                       "m=video %s RTP/AVP 33\r\n"
+                       "a=rtpmap:33 MP2T/90000\r\n"
+                       "a=rtcp:1235\r\n"
+//                       "a=lang:de\r\n"
+                       , service_name, service_provider, host, serv);
+
+    //for(j=0; j<60; j++) printf("%02x-", sdt[j]);
+    //printf(" - rtp://@%s:%s %s %s - (%d) %ld bytes\n",
+    //       host, serv, service_provider, service_name, sid, 
worker-buffer);
+
+    // sending this announcement
+    if ( sendto(i_sap_handle , buffer , worker-buffer , 0 ,
+                (struct sockaddr*)&addr , sizeof(addr)) < 0 )
+    {
+        msg_Err( NULL, "couldn't send to %d (%s)",
+                 i_sap_handle, strerror(errno) );
+    }
+}
+
+void sap_Close(void)
+{
+    if(i_sap_handle >= 0)
+	close( i_sap_handle );
+
+}
+
diff --git a/sap.h b/sap.h
new file mode 100644
index 0000000..8e1d734
--- /dev/null
+++ b/sap.h
@@ -0,0 +1,38 @@
+/*****************************************************************************
+ * sap.h SAP Announcements generated from SDT
+ 
*****************************************************************************
+ * Copyright Tripleplay service 2004,2005,2011
+ *
+ * Author:  Dirk Braunschweiger <dirkmb at selfnet.de>
+ *          Markus Wick         <markus at selfnet.de>
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 
02110-1301, USA.
+ 
*****************************************************************************/
+
+#ifndef SAP_H
+#define SAP_H
+
+// Define the dump period in seconds
+#define SAP_INTERVAL   1
+#define SAP_IPv4_DEST  "239.195.255.255"
+#define SAP_IPv4_DPORT 9875
+#define SAP_IPv4_TTL   255
+
+
+void sap_Init(void);
+void sap_Announce(void);
+void sap_Close(void);
+
+#endif
-- 
1.7.2.5



More information about the dvblast-devel mailing list