[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