[dvblast-devel] [PATCH] Support for Deltacast ASI card

Simon Lockhart simon at slimey.org
Thu Jun 20 22:22:50 CEST 2013


On Wed Jun 05, 2013 at 08:29:34AM +0100, Simon Lockhart wrote:
> I've found a card from Deltacast:
> 
>   http://www.deltacast.tv/Products/DELTA-asi-OEM-video-input-output-PCI-Express-card.asp
> 
> Up to 8 ASI receive channels on one card (although it can only fit 6 inputs on
> the back of one card, so the last 2 are on a seperate backpanel), and comes 
> with Linux drivers and SDK. OEM pricing is a lot cheaper than the DVEO card.

Well, I got the cards from them, and have added support to DVBlast. Patch
below ("git diff HEAD")

This is my first attempt at a patch to DVBlast, so feel free to critique...

Hope this is helpful to people...

Simon



diff --git a/AUTHORS b/AUTHORS
index 3535fd0..c1d2df2 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -37,3 +37,7 @@ N: Jean-Paul Saman
 E: jpsaman AT videolan DOT org
 C: jpsaman
 D: DVB-S2 bug fixes, syslog support
+
+N: Simon Lockhart
+E: simon AT slimey DOT org
+D: Deltacast ASI card support
diff --git a/INSTALL b/INSTALL
index 1785bcc..6c1be8f 100644
--- a/INSTALL
+++ b/INSTALL
@@ -27,3 +27,7 @@ To install biTStream, clone git repository and run `make install`.
     git clone git://git.videolan.org/bitstream.git
     cd bitstream
     make install
+
+If you wish to support Deltacast ASI cards, you will first need to install
+the Deltacast StreamMaster drivers and SDK, which are downloadable from the
+Deltacast website (login required).
diff --git a/Makefile b/Makefile
index adc924d..3b6775c 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,7 @@ VERSION_MINOR = 2
 TOPDIR = `basename ${PWD}`
 GIT_VER = $(shell git describe --tags --dirty --always 2>/dev/null)
 uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
+deltacast_inc := $(shell sh -c 'test -f /usr/include/StreamMaster.h && echo -n Y')
 
 CFLAGS += -Wall -Wformat-security -O3 -fomit-frame-pointer
 CFLAGS += -g
@@ -22,9 +23,14 @@ ifeq ($(uname_S),Darwin)
 LDLIBS += -liconv
 endif
 
+ifeq ($(deltacast_inc),Y)
+CFLAGS += -DHAVE_ASI_DELTACAST_SUPPORT
+LDLIBS += -lstreammaster
+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 asi-deltacast.o
 OBJ_DVBLASTCTL = util.o dvblastctl.o
 
 ifndef V
@@ -43,7 +49,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 asi-deltacast.h
 	@echo "CC      $<"
 	$(Q)$(CROSS)$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
 
diff --git a/NEWS b/NEWS
index eb5ea32..76a6d5f 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,7 @@ Changes between 2.2 and 2.3:
     globally and per output.
   * Added support for multi-delivery system frontends.
   * Added support for multistream that appeared in Linux 3.6
+  * Added support for Deltacast ASI cards
 
 Changes between 2.1 and 2.2:
 ----------------------------
diff --git a/README b/README
index bc0a9d3..207896e 100644
--- a/README
+++ b/README
@@ -73,6 +73,11 @@ If you own a Computer Modules DVB-ASI input card, you can have DVBlast
 filter and demultiplex the inputs. You just need to specify the slot number
 with -A.
 
+If you own a Deltacast ASI input card, you can have DVBlast filter and 
+demultiplex the inputs. You just need to specify the input as 
+"-A deltacast:<x>" where <x> is 100 * the card number (0 based) + the channel
+number (0 based).
+
 DVBlast can also read from a UDP or RTP IPv4 source carrying for
 instance a multi-program transport stream. The address is specified with
 -D. See the 'advanced features' section for information on how to create
diff --git a/asi-deltacast.c b/asi-deltacast.c
new file mode 100644
index 0000000..b9fdefa
--- /dev/null
+++ b/asi-deltacast.c
@@ -0,0 +1,220 @@
+/*****************************************************************************
+ * asi-deltacast.c: support for Deltacast ASI cards
+ *****************************************************************************
+ * Copyright (C) 2004, 2009 VideoLAN
+ *
+ * Authors: Simon Lockhart <simon at slimey.org>
+ *
+ * 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 "config.h"
+
+#ifdef HAVE_ASI_DELTACAST_SUPPORT
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/uio.h>
+#include <sys/poll.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+
+#include <bitstream/common.h>
+
+#include <StreamMaster.h>
+// #include <DeltacastErrors.h>
+
+#include "asi-deltacast.h"
+
+#include "dvblast.h"
+
+/*****************************************************************************
+ * Local declarations
+ *****************************************************************************/
+
+static HANDLE h_board, h_channel;
+
+static UCHAR *p_asibuf = NULL;
+static ULONG i_asibuf_len;
+
+/*****************************************************************************
+ * asi_deltacast_Open
+ *****************************************************************************/
+void asi_deltacast_Open( void )
+{
+    ASICHANNELCONFIG RXConfig;
+    ULONG ApiVersion, DrvVersion, NbBoards;
+    ASIBOARDINFOEX BoardInfoEx;
+    BOOL res;
+
+    /* Get API information */
+    res = Asi_GetApiInfo(&ApiVersion,&DrvVersion,&NbBoards);
+    if (!res)
+    {
+        msg_Err( NULL, "couldn't get Deltacast API Info: 0x%08lX",
+                 		(unsigned long) Dc_GetLastError(NULL) );
+        exit(EXIT_FAILURE);
+    }
+
+    msg_Dbg( NULL, "Deltacast StreamMaster DLL v%d.%d", 
+			(int)ApiVersion>>16, 
+			(int)ApiVersion&0xFFFF);
+    msg_Dbg( NULL, "Deltacast Driver v%d.%d.%d", 
+			(DrvVersion >> 24) & 0xFF,
+			(DrvVersion >> 16) & 0xFF,
+			(DrvVersion >>  8) & 0xFF);
+    msg_Dbg( NULL, "Deltacast Board Count: %d", NbBoards);
+
+    /* Get the board information */
+    res = Asi_GetBoardInfoEx((int)(i_asi_adapter / 100), &BoardInfoEx);
+    if (!res)
+    {
+        msg_Err( NULL, "couldn't get Deltacast board Info: 0x%08lX",
+                 		(unsigned long) Dc_GetLastError(NULL) );
+        exit(EXIT_FAILURE);
+    }
+
+    msg_Dbg( NULL, "Deltacast Board FPGA v%08lX", 
+		(unsigned long)BoardInfoEx.BaseInformation.FPGAVersion);
+    msg_Dbg( NULL, "Deltacast Board PLD v%08lX", 
+		(unsigned long)BoardInfoEx.BaseInformation.PLDVersion);
+    msg_Dbg( NULL, "Deltacast Board PLX v%08lX", 
+		(unsigned long)BoardInfoEx.BaseInformation.PLXRevision);
+    msg_Dbg( NULL, "Deltacast Board Serial %08X%08X", 
+		(ULONG)(BoardInfoEx.BaseInformation.SerialNb>>32),
+		(ULONG)(BoardInfoEx.BaseInformation.SerialNb&0xFFFFFFFF));
+    msg_Dbg( NULL, "Deltacast Board Input Count: %d", BoardInfoEx.NbRxChannels_i);
+    msg_Dbg( NULL, "Deltacast Board Output Count: %d", BoardInfoEx.NbTxChannels_i);
+
+    /* Open the board */
+    h_board = Asi_SetupBoard((int)(i_asi_adapter / 100));
+    if (h_board == NULL)
+    {
+        msg_Err( NULL, "couldn't setup deltacast board %d: 0x%08lX",
+                 (int)(i_asi_adapter / 100), (unsigned long) Dc_GetLastError(NULL) );
+        exit(EXIT_FAILURE);
+    }
+
+    /* Open the channel on the board */
+    memset(&RXConfig,0,sizeof(ASICHANNELCONFIG));
+    RXConfig.DriverBufferSize  = 188*2400;/* Use a driver buffer size of 2400 packets */
+    RXConfig.BoardBufferSize   = 1048576;                /* Use 1MB of onboard buffer */
+    RXConfig.TSPacketType      = ASI_PKT_188;             /* Use 188-bytes TS packets */
+    RXConfig.NbPIDFilter       = 0;                               /* No PID filtering */
+    RXConfig.pPIDFilterTable   = NULL;                            /* No PID filtering */
+    RXConfig.BitrateIntPeriod  = ASI_INTPER_100;           /* Integrate over 100 msec */
+    RXConfig.AllowedBRDeviation= 10000000;               /* Allow 10Mbps of deviation */
+    RXConfig.RXTimeStamp       = FALSE;                            /* No timestamping */
+
+    /* Try to open RX0 channel on the board 0 */
+    h_channel = Asi_OpenChannel(h_board, ASI_CHN_RX0 + (i_asi_adapter % 100), &RXConfig);
+    if (h_channel == NULL)
+    {
+        msg_Err( NULL, "couldn't setup deltacast channel %d: 0x%08lX",
+                 (i_asi_adapter % 100), (unsigned long) Dc_GetLastError(NULL) );
+        exit(EXIT_FAILURE);
+    }
+}
+
+/*****************************************************************************
+ * asi_deltacast_Read : read packets from the device
+ *****************************************************************************/
+block_t *asi_deltacast_Read( mtime_t i_poll_timeout )
+{
+    BOOL res;
+    block_t *p_ts, **pp_current = &p_ts;
+    int i;
+    ULONG Err;
+    struct pollfd pfd[2];
+    int i_ret, i_nb_fd = 1;
+
+    if (i_comm_fd != -1)
+    {
+        pfd[0].fd = i_comm_fd;
+        pfd[0].events = POLLIN;
+
+	i_ret = poll(pfd, i_nb_fd, 0);
+
+	if (i_ret > 0 && pfd[0].revents)
+	    comm_Read();
+    }
+
+    res = Asi_GetInputBuffer(h_channel, &p_asibuf, &i_asibuf_len,
+						i_poll_timeout);
+    if (!res)
+    {
+        Err = Dc_GetLastError(NULL) & ~DC_ERRORCODE_MASK;
+
+        if (Err != DCERR_TIMEOUT)
+        {
+          msg_Warn( NULL, "asi_deltacast_Read(): GetInputBuffer failed: 0x%08X!", Err);
+        }
+        return NULL;
+    }
+
+    i_wallclock = mdate();
+
+    for (i = 0; i < i_asibuf_len / TS_SIZE; i++)
+    {
+        *pp_current = block_New();
+	memcpy((*pp_current)->p_ts, p_asibuf + (i * TS_SIZE), TS_SIZE);
+        pp_current = &(*pp_current)->p_next;
+
+    }
+
+    res = Asi_ReleaseInputBuffer(h_channel);
+
+//    msg_Warn( NULL, "asi_deltacast_Read(): returning %d blocks", i_asibuf_len / TS_SIZE );
+    return p_ts;
+}
+
+/*****************************************************************************
+ * asi_deltacast_SetFilter
+ *****************************************************************************/
+int asi_deltacast_SetFilter( uint16_t i_pid )
+{
+    /* TODO: Support PID filtering */
+    msg_Warn( NULL, "asi_deltacast_SetFilter(%d) not yet implemented", i_pid );
+    return -1;
+}
+
+/*****************************************************************************
+ * asi_deltacast_UnsetFilter: normally never called
+ *****************************************************************************/
+void asi_deltacast_UnsetFilter( int i_fd, uint16_t i_pid )
+{
+    /* TODO: Support PID filtering */
+    msg_Warn( NULL, "asi_deltacast_UnsetFilter() not yet implemented" );
+}
+
+/*****************************************************************************
+ * asi_deltacast_Reset
+ *****************************************************************************/
+void asi_deltacast_Reset( void )
+{
+    /* Called when retune required, so nothing required */
+    msg_Warn( NULL, "asi_deltacast_Reset() do nothing" );
+}
+
+#endif
diff --git a/asi-deltacast.h b/asi-deltacast.h
new file mode 100644
index 0000000..25f4df9
--- /dev/null
+++ b/asi-deltacast.h
@@ -0,0 +1,42 @@
+/*****************************************************************************
+ * asi-deltacast.h: support for Deltacast ASI cards
+ *****************************************************************************
+ * Copyright (C) 2004, 2009 VideoLAN
+ *
+ * Authors: Simon Lockhart <simon at slimey.org>
+ *
+ * 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 _ASI_DELTACAST_H
+#define _ASI_DELTACAST_H
+
+typedef enum error_source
+{
+   DCERR_SRC_WIN32 = 0,    /*! Win32 error code */
+   DCERR_SRC_SDI_API,      /*! DELTA-sdi VIDEOMASTER error code */
+   DCERR_SRC_SDI_DRIVER,   /*! DELTA-sdi DRIVER error code */
+   DCERR_SRC_STREAMMASTER, /*! DELTA-asi StreamMaster error code */
+   DCERR_SRC_SYSTEMSMASTER /*! DELTA-asi SystemsMaster error code */
+} ERRORSOURCE;
+
+ULONG WINAPI Dc_GetLastError (ERRORSOURCE *pErrorSource);
+
+#define DC_ERRORCODE_MASK      0x2FFF0000                                            /* facility mask */
+#define DCERR_TIMEOUT                  0x80000201  /*! A time-out occured */
+
+
+#endif
+
diff --git a/dvblast.1 b/dvblast.1
index 51ca109..b0249f7 100644
--- a/dvblast.1
+++ b/dvblast.1
@@ -31,7 +31,9 @@ files, only DVB devices. If you were looking for these features, switch to VLC.
 Address of the adapter
 .TP
 \fB\-A\fR, \fB\-\-asi\-adapter\fR
-Read packets from an ASI adapter (0-n)
+Read packets from an ASI adapter (0-n). If support for Deltacast ASI cards is
+compiled in, prefix the adapter number with "deltacast:" to select a Deltacast
+input. Deltacast inputs are numbered as (100 * card number) + channel number.
 .TP
 \fB\-b\fR, \fB\-\-bandwidth\fR <bandwidth>
 Frontend bandwidth
diff --git a/dvblast.c b/dvblast.c
index 03186f8..b9a0d4f 100644
--- a/dvblast.c
+++ b/dvblast.c
@@ -854,15 +854,32 @@ int main( int i_argc, char **pp_argv )
             break;
 
         case 'A':
-            i_asi_adapter = strtol( optarg, NULL, 0 );
+#ifdef HAVE_ASI_SUPPORT
             if ( pf_Open != NULL )
                 usage();
-#ifdef HAVE_ASI_SUPPORT
-            pf_Open = asi_Open;
-            pf_Read = asi_Read;
-            pf_Reset = asi_Reset;
-            pf_SetFilter = asi_SetFilter;
-            pf_UnsetFilter = asi_UnsetFilter;
+            if ( strncmp(optarg, "deltacast:", 10) == 0)
+            {
+#ifdef HAVE_ASI_DELTACAST_SUPPORT
+                i_asi_adapter = strtol( optarg+10, NULL, 0 );
+                pf_Open = asi_deltacast_Open;
+                pf_Read = asi_deltacast_Read;
+                pf_Reset = asi_deltacast_Reset;
+                pf_SetFilter = asi_deltacast_SetFilter;
+                pf_UnsetFilter = asi_deltacast_UnsetFilter;
+#else
+                msg_Err( NULL, "DVBlast is compiled without Deltacast ASI support.");
+                exit(1);
+#endif
+	    }
+	    else
+	    {
+                i_asi_adapter = strtol( optarg, NULL, 0 );
+                pf_Open = asi_Open;
+                pf_Read = asi_Read;
+                pf_Reset = asi_Reset;
+                pf_SetFilter = asi_SetFilter;
+                pf_UnsetFilter = asi_UnsetFilter;
+	    }
 #else
             msg_Err( NULL, "DVBlast is compiled without ASI support.");
             exit(1);
diff --git a/dvblast.h b/dvblast.h
index afae63c..e7f0c68 100644
--- a/dvblast.h
+++ b/dvblast.h
@@ -284,6 +284,14 @@ void asi_Reset( void );
 int asi_SetFilter( uint16_t i_pid );
 void asi_UnsetFilter( int i_fd, uint16_t i_pid );
 
+#ifdef HAVE_ASI_DELTACAST_SUPPORT
+void asi_deltacast_Open( void );
+block_t * asi_deltacast_Read( mtime_t i_poll_timeout );
+void asi_deltacast_Reset( void );
+int asi_deltacast_SetFilter( uint16_t i_pid );
+void asi_deltacast_UnsetFilter( int i_fd, uint16_t i_pid );
+#endif
+
 void demux_Open( void );
 void demux_Run( block_t *p_ts );
 void demux_Change( output_t *p_output, const output_config_t *p_config );


More information about the dvblast-devel mailing list