mirror of
https://github.com/outbackdingo/UltraGrid.git
synced 2026-03-22 08:40:28 +00:00
Added Deltacast DVI grabber
This commit is contained in:
@@ -54,6 +54,8 @@ AC_SUBST(LIBS)
|
||||
AC_SUBST(OBJS)
|
||||
AC_SUBST(POST_COMPILE_MSG)
|
||||
|
||||
AC_CHECK_SIZEOF([int *])
|
||||
|
||||
AC_C_BIGENDIAN(
|
||||
AC_DEFINE([WORDS_BIGENDIAN], 1, [This is big endian system]),
|
||||
AC_DEFINE([WORDS_SMALLENDIAN], 1, [This is little endian system])
|
||||
@@ -972,7 +974,7 @@ then
|
||||
then
|
||||
DELTACAST_INC="-I$DELTACAST_PATH/$HEADER_SUBDIR"
|
||||
fi
|
||||
DELTACAST_CAP_OBJ="src/video_capture/deltacast.o"
|
||||
DELTACAST_CAP_OBJ="src/video_capture/deltacast.o src/video_capture/deltacast_dvi.o"
|
||||
DELTACAST_DISP_OBJ="src/video_display/deltacast.o"
|
||||
AC_DEFINE([HAVE_DELTACAST], [1], [Build with DELTACAST support])
|
||||
AC_SUBST(DELTACAST_CAP_LIB_TARGET, "lib/ultragrid/vidcap_deltacast.so.$video_capture_abi_version")
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#include "video_capture/bluefish444.h"
|
||||
#include "video_capture/decklink.h"
|
||||
#include "video_capture/deltacast.h"
|
||||
#include "video_capture/deltacast_dvi.h"
|
||||
#include "video_capture/dvs.h"
|
||||
#include "video_capture/linsys.h"
|
||||
#include "video_capture/null.h"
|
||||
@@ -194,6 +195,16 @@ struct vidcap_device_api vidcap_device_table[] = {
|
||||
MK_NAME(vidcap_deltacast_grab),
|
||||
NULL
|
||||
},
|
||||
{
|
||||
0,
|
||||
"deltacast-dvi",
|
||||
MK_NAME(vidcap_deltacast_dvi_probe),
|
||||
MK_NAME(vidcap_deltacast_dvi_init),
|
||||
MK_NAME(vidcap_deltacast_dvi_finish),
|
||||
MK_NAME(vidcap_deltacast_dvi_done),
|
||||
MK_NAME(vidcap_deltacast_dvi_grab),
|
||||
NULL
|
||||
},
|
||||
#endif /* HAVE_DELTACAST */
|
||||
#if defined HAVE_LINSYS || defined BUILD_LIBRARIES
|
||||
{
|
||||
|
||||
700
src/video_capture/deltacast_dvi.cpp
Normal file
700
src/video_capture/deltacast_dvi.cpp
Normal file
@@ -0,0 +1,700 @@
|
||||
/*
|
||||
* FILE: video_capture/deltacast.c
|
||||
* AUTHORS: Martin Benes <martinbenesh@gmail.com>
|
||||
* Lukas Hejtmanek <xhejtman@ics.muni.cz>
|
||||
* Petr Holub <hopet@ics.muni.cz>
|
||||
* Milos Liska <xliska@fi.muni.cz>
|
||||
* Jiri Matela <matela@ics.muni.cz>
|
||||
* Dalibor Matura <255899@mail.muni.cz>
|
||||
* Ian Wesley-Smith <iwsmith@cct.lsu.edu>
|
||||
*
|
||||
* Copyright (c) 2005-2010 CESNET z.s.p.o.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, is permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
*
|
||||
* This product includes software developed by CESNET z.s.p.o.
|
||||
*
|
||||
* 4. Neither the name of the CESNET nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "host.h"
|
||||
#include "config.h"
|
||||
#include "config_unix.h"
|
||||
#include "config_win32.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "video_codec.h"
|
||||
#include "video_capture.h"
|
||||
|
||||
#include "tv.h"
|
||||
|
||||
#include "audio/audio.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#ifndef WIN32
|
||||
#include <sys/poll.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
#include <semaphore.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // END of extern "C"
|
||||
#endif
|
||||
|
||||
#include "video_capture/deltacast_dvi.h"
|
||||
|
||||
#include <VideoMasterHD_Core.h>
|
||||
#include <VideoMasterHD_Dvi.h>
|
||||
|
||||
static volatile bool should_exit = false;
|
||||
|
||||
struct vidcap_deltacast_dvi_state {
|
||||
struct video_frame *frame;
|
||||
struct tile *tile;
|
||||
HANDLE BoardHandle, StreamHandle;
|
||||
HANDLE SlotHandle;
|
||||
|
||||
struct timeval t, t0;
|
||||
int frames;
|
||||
};
|
||||
|
||||
#define EEDDIDOK 0
|
||||
#define BADEEDID 1
|
||||
|
||||
static void usage(void);
|
||||
static BOOL CheckEEDID(BYTE pEEDIDBuffer[256]);
|
||||
static const char * GetErrorDescription(ULONG CodeError);
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
ULONG Result,DllVersion,NbBoards;
|
||||
int i;
|
||||
printf("-t deltacast[:board=<index>][:codec=<color_spec>][:edid=<edid>]"
|
||||
"[:channel=<channel>]\n");
|
||||
Result = VHD_GetApiInfo(&DllVersion,&NbBoards);
|
||||
if (Result != VHDERR_NOERROR) {
|
||||
fprintf(stderr, "[DELTACAST] ERROR : Cannot query VideoMasterHD"
|
||||
" information. Result = 0x%08X\n",
|
||||
Result);
|
||||
return;
|
||||
}
|
||||
if (NbBoards == 0) {
|
||||
fprintf(stderr, "[DELTACAST] No DELTA board detected, exiting...\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("\t<index> - index of DVI card\n");
|
||||
printf("\tAvailable cards:\n");
|
||||
/* Query DELTA boards information */
|
||||
for (ULONG i = 0; i < NbBoards; i++)
|
||||
{
|
||||
ULONG BoardType;
|
||||
HANDLE BoardHandle = NULL;
|
||||
Result = VHD_OpenBoardHandle(i,&BoardHandle,NULL,0);
|
||||
VHD_GetBoardProperty(BoardHandle, VHD_CORE_BP_BOARD_TYPE, &BoardType);
|
||||
if (Result == VHDERR_NOERROR)
|
||||
{
|
||||
printf("\t\tBoard %d: ", i);
|
||||
switch(BoardType)
|
||||
{
|
||||
case VHD_BOARDTYPE_HD : printf("HD board type"); break;
|
||||
case VHD_BOARDTYPE_HDKEY : printf("HD key board type"); break;
|
||||
case VHD_BOARDTYPE_SD : printf("SD board type"); break;
|
||||
case VHD_BOARDTYPE_SDKEY : printf("SD key board type"); break;
|
||||
case VHD_BOARDTYPE_DVI : printf("DVI board type"); break;
|
||||
case VHD_BOARDTYPE_CODEC : printf("CODEC board type"); break;
|
||||
case VHD_BOARDTYPE_3G : printf("3G board type"); break;
|
||||
case VHD_BOARDTYPE_3GKEY : printf("3G key board type"); break;
|
||||
default : printf("Unknown board type"); break;
|
||||
}
|
||||
printf("\n");
|
||||
VHD_CloseBoardHandle(BoardHandle);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\t<edid> may be one of following\n");
|
||||
printf("\t\t0 - load DVI-D EEDID\n");
|
||||
printf("\t\t1 - load DVI-A EEDID\n");
|
||||
printf("\t\t2 - load HDMI EEDID\n");
|
||||
printf("\t\t3 - avoid EEDID loading\n");
|
||||
|
||||
printf("\t<color_spec> may be one of following\n");
|
||||
printf("\t\tUYVY (default)\n");
|
||||
printf("\t\tRGBA\n");
|
||||
printf("\t\tRGB\n");
|
||||
|
||||
printf("\t<channel> may be channel index (for cards which have multiple inputs)\n");
|
||||
|
||||
}
|
||||
|
||||
static BOOL CheckEEDID(BYTE pEEDIDBuffer[256])
|
||||
{
|
||||
|
||||
int i;
|
||||
UBYTE sum1 = 0,sum2 = 0;
|
||||
BOOL Return = EEDDIDOK;
|
||||
|
||||
/* Verify checksum */
|
||||
for(i=0;i<128;i++)
|
||||
{
|
||||
sum1 += pEEDIDBuffer[i];
|
||||
sum2 += pEEDIDBuffer[i+128];
|
||||
}
|
||||
if(sum1 != 0 || sum2 != 0)
|
||||
Return = BADEEDID;
|
||||
|
||||
/* Verify header */
|
||||
if(pEEDIDBuffer[0] != 0x00u || pEEDIDBuffer[1] != 0xFFu || pEEDIDBuffer[2] != 0xFFu || pEEDIDBuffer[3] != 0xFFu
|
||||
|| pEEDIDBuffer[4] != 0xFFu || pEEDIDBuffer[5] != 0xFFu || pEEDIDBuffer[6] != 0xFFu || pEEDIDBuffer[7] != 0x00u)
|
||||
Return = BADEEDID;
|
||||
|
||||
return Return;
|
||||
}
|
||||
|
||||
static const char * GetErrorDescription(ULONG CodeError)
|
||||
{
|
||||
switch (CodeError)
|
||||
{
|
||||
case VHDERR_NOERROR : return "No error";
|
||||
case VHDERR_FATALERROR : return "Fatal error occurred (should re-install)";
|
||||
case VHDERR_OPERATIONFAILED : return "Operation failed (undefined error)";
|
||||
case VHDERR_NOTENOUGHRESOURCE : return "Not enough resource to complete the operation";
|
||||
case VHDERR_NOTIMPLEMENTED : return "Not implemented yet";
|
||||
case VHDERR_NOTFOUND : return "Required element was not found";
|
||||
case VHDERR_BADARG : return "Bad argument value";
|
||||
case VHDERR_INVALIDPOINTER : return "Invalid pointer";
|
||||
case VHDERR_INVALIDHANDLE : return "Invalid handle";
|
||||
case VHDERR_INVALIDPROPERTY : return "Invalid property index";
|
||||
case VHDERR_INVALIDSTREAM : return "Invalid stream or invalid stream type";
|
||||
case VHDERR_RESOURCELOCKED : return "Resource is currently locked";
|
||||
case VHDERR_BOARDNOTPRESENT : return "Board is not available";
|
||||
case VHDERR_INCOHERENTBOARDSTATE : return "Incoherent board state or register value";
|
||||
case VHDERR_INCOHERENTDRIVERSTATE : return "Incoherent driver state";
|
||||
case VHDERR_INCOHERENTLIBSTATE : return "Incoherent library state";
|
||||
case VHDERR_SETUPLOCKED : return "Configuration is locked";
|
||||
case VHDERR_CHANNELUSED : return "Requested channel is already used or doesn't exist";
|
||||
case VHDERR_STREAMUSED : return "Requested stream is already used";
|
||||
case VHDERR_READONLYPROPERTY : return "Property is read-only";
|
||||
case VHDERR_OFFLINEPROPERTY : return "Property is off-line only";
|
||||
case VHDERR_TXPROPERTY : return "Property is of TX streams";
|
||||
case VHDERR_TIMEOUT : return "Time-out occurred";
|
||||
case VHDERR_STREAMNOTRUNNING : return "Stream is not running";
|
||||
case VHDERR_BADINPUTSIGNAL : return "Bad input signal, or unsupported standard";
|
||||
case VHDERR_BADREFERENCESIGNAL : return "Bad genlock signal or unsupported standard";
|
||||
case VHDERR_FRAMELOCKED : return "Frame already locked";
|
||||
case VHDERR_FRAMEUNLOCKED : return "Frame already unlocked";
|
||||
case VHDERR_INCOMPATIBLESYSTEM : return "Selected video standard is incompatible with running clock system";
|
||||
case VHDERR_ANCLINEISEMPTY : return "ANC line is empty";
|
||||
case VHDERR_ANCLINEISFULL : return "ANC line is full";
|
||||
case VHDERR_BUFFERTOOSMALL : return "Buffer too small";
|
||||
case VHDERR_BADANC : return "Received ANC aren't standard";
|
||||
case VHDERR_BADCONFIG : return "Invalid configuration";
|
||||
case VHDERR_FIRMWAREMISMATCH : return "The loaded firmware is not compatible with the installed driver";
|
||||
case VHDERR_LIBRARYMISMATCH : return "The loaded VideomasterHD library is not compatible with the installed driver";
|
||||
case VHDERR_FAILSAFE : return "The fail safe firmware is loaded. You need to upgrade your firmware";
|
||||
case VHDERR_RXPROPERTY : return "Property is of RX streams";
|
||||
default: return "Unknown code error";
|
||||
}
|
||||
}
|
||||
|
||||
struct vidcap_type *
|
||||
vidcap_deltacast_dvi_probe(void)
|
||||
{
|
||||
struct vidcap_type* vt;
|
||||
|
||||
vt = (struct vidcap_type *) malloc(sizeof(struct vidcap_type));
|
||||
if (vt != NULL) {
|
||||
vt->id = VIDCAP_DELTACAST_DVI_ID;
|
||||
vt->name = "deltacast-dvi";
|
||||
vt->description = "DELTACAST DVI card";
|
||||
}
|
||||
return vt;
|
||||
}
|
||||
|
||||
void *
|
||||
vidcap_deltacast_dvi_init(char *init_fmt, unsigned int flags)
|
||||
{
|
||||
struct vidcap_deltacast_dvi_state *s;
|
||||
ULONG Result = VHDERR_NOERROR,DllVersion,NbBoards,BoardType;
|
||||
ULONG BrdId = 0;
|
||||
ULONG Packing;
|
||||
ULONG Status = 0;
|
||||
ULONG Width = 0, Height = 0, RefreshRate = 0;
|
||||
BOOL Interlaced_B = FALSE;
|
||||
VHD_DVI_MODE DviMode = NB_VHD_DVI_MODES;
|
||||
int edid = -1;
|
||||
BYTE pEEDIDBuffer[256];
|
||||
ULONG pEEDIDBufferSize=256;
|
||||
codec_t codec = UYVY;
|
||||
int channel = 0;
|
||||
ULONG ChannelId;
|
||||
|
||||
int i;
|
||||
|
||||
printf("vidcap_deltacast_dvi_init\n");
|
||||
|
||||
s = (struct vidcap_deltacast_dvi_state *) malloc(sizeof(struct vidcap_deltacast_dvi_state));
|
||||
|
||||
if(s == NULL) {
|
||||
printf("Unable to allocate DELTACAST state\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s->BoardHandle = s->StreamHandle = s->SlotHandle = NULL;
|
||||
|
||||
if(init_fmt && strcmp(init_fmt, "help") == 0) {
|
||||
usage();
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(init_fmt)
|
||||
{
|
||||
char *save_ptr = NULL;
|
||||
char *tok;
|
||||
int pos = 0;
|
||||
|
||||
while((tok = strtok_r(init_fmt, ":", &save_ptr)) != NULL) {
|
||||
if(strncasecmp(tok, "board=", strlen("board=")) == 0) {
|
||||
BrdId = atoi(tok + strlen("board="));
|
||||
} else if(strncasecmp(tok, "codec=", strlen("codec=")) == 0) {
|
||||
char *codec_str = tok + strlen("codec=");
|
||||
|
||||
for (i = 0; codec_info[i].name != NULL; i++) {
|
||||
if (strcmp(codec_str, codec_info[i].name) == 0) {
|
||||
codec = codec_info[i].codec;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(codec_info[i].name == NULL) {
|
||||
fprintf(stderr, "Unable to find codec: %s\n",
|
||||
codec_str);
|
||||
goto error;
|
||||
}
|
||||
} else if(strncasecmp(tok, "edid=", strlen("edid=")) == 0) {
|
||||
edid = atoi(tok + strlen("edid="));
|
||||
if(edid < 0 || edid > 3) {
|
||||
fprintf(stderr, "[DELTA] Error: Wrong "
|
||||
"EDID entered on commandline. "
|
||||
"Expected 0-3, got %d.\n", edid);
|
||||
goto error;
|
||||
|
||||
}
|
||||
} else if(strncasecmp(tok, "channel=", strlen("channel=")) == 0) {
|
||||
channel = atoi(tok + strlen("channel="));
|
||||
} else {
|
||||
fprintf(stderr, "[DELTA] Error: Unrecongnized "
|
||||
"trailing parameter %s\n", tok);
|
||||
goto error;
|
||||
}
|
||||
init_fmt = NULL;
|
||||
}
|
||||
} else {
|
||||
BrdId = 0;
|
||||
printf("[DELTACAST] Automatically choosen device nr. 0\n");
|
||||
}
|
||||
|
||||
/* Query VideoMasterHD information */
|
||||
Result = VHD_GetApiInfo(&DllVersion,&NbBoards);
|
||||
if (Result != VHDERR_NOERROR) {
|
||||
fprintf(stderr, "[DELTACAST] ERROR : Cannot query VideoMasterHD"
|
||||
" information. Result = 0x%08X\n",
|
||||
Result);
|
||||
goto error;
|
||||
}
|
||||
if (NbBoards == 0) {
|
||||
fprintf(stderr, "[DELTACAST] No DELTA board detected, exiting...\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(BrdId >= NbBoards) {
|
||||
fprintf(stderr, "[DELTACAST] Wrong index %d. Found %d cards.\n", BrdId, NbBoards);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Open a handle on first DELTA-hd/sdi/codec board */
|
||||
Result = VHD_OpenBoardHandle(BrdId,&s->BoardHandle,NULL,0);
|
||||
if (Result != VHDERR_NOERROR)
|
||||
{
|
||||
fprintf(stderr, "[DELTACAST] ERROR : Cannot open DELTA board %u handle. Result = 0x%08X\n",BrdId,Result);
|
||||
goto error;
|
||||
}
|
||||
VHD_GetBoardProperty(s->BoardHandle, VHD_CORE_BP_BOARD_TYPE, &BoardType);
|
||||
if(BoardType!=VHD_BOARDTYPE_DVI) {
|
||||
fprintf(stderr, "[DELTACAST] ERROR : The selected board is not an DVI one\n");
|
||||
goto bad_channel;
|
||||
}
|
||||
|
||||
switch(channel) {
|
||||
case 0:
|
||||
ChannelId = VHD_ST_RX0;
|
||||
break;
|
||||
case 1:
|
||||
ChannelId = VHD_ST_RX1;
|
||||
break;
|
||||
case 2:
|
||||
ChannelId = VHD_ST_RX2;
|
||||
break;
|
||||
case 3:
|
||||
ChannelId = VHD_ST_RX3;
|
||||
break;
|
||||
}
|
||||
Result = VHD_OpenStreamHandle(s->BoardHandle, ChannelId, VHD_DVI_STPROC_DEFAULT,
|
||||
NULL, &s->StreamHandle, NULL);
|
||||
if (Result != VHDERR_NOERROR)
|
||||
{
|
||||
fprintf(stderr, "ERROR : Cannot open RX0 stream on DELTA-DVI board handle. "
|
||||
"Result = 0x%08X\n",Result);
|
||||
goto no_stream;
|
||||
}
|
||||
|
||||
/* Read EEDID and check its validity */
|
||||
Result = VHD_ReadEEDID(s->BoardHandle,VHD_ST_RX0,pEEDIDBuffer,&pEEDIDBufferSize);
|
||||
if(Result == VHDERR_NOTIMPLEMENTED || CheckEEDID(pEEDIDBuffer) == BADEEDID)
|
||||
{
|
||||
/* Propose edid preset to user and load */
|
||||
fprintf(stderr, "\nNo valid EEDID detected or DELTA-dvi board V1.\n");
|
||||
fprintf(stderr, "Please set it as a command-line option.\n");
|
||||
goto no_stream;
|
||||
}
|
||||
switch(edid)
|
||||
{
|
||||
case 0 : VHD_PresetEEDID(VHD_EEDID_DVID,pEEDIDBuffer,256);
|
||||
VHD_LoadEEDID(s->StreamHandle,pEEDIDBuffer,256);
|
||||
break;
|
||||
case 1 : VHD_PresetEEDID(VHD_EEDID_DVIA,pEEDIDBuffer,256);
|
||||
VHD_LoadEEDID(s->StreamHandle,pEEDIDBuffer,256);
|
||||
break;
|
||||
case 2 : VHD_PresetEEDID(VHD_EEDID_HDMI,pEEDIDBuffer,256);
|
||||
VHD_LoadEEDID(s->StreamHandle,pEEDIDBuffer,256);
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
|
||||
/* Wait for channel locked */
|
||||
printf("\nWaiting for incoming signal...\n");
|
||||
do
|
||||
{
|
||||
Result = VHD_GetStreamProperty(s->StreamHandle, VHD_DVI_SP_MODE, (ULONG *) &DviMode);
|
||||
} while (Result != VHDERR_NOERROR && !should_exit);
|
||||
|
||||
if(Result != VHDERR_NOERROR)
|
||||
goto no_format;
|
||||
|
||||
printf("\nIncoming Dvi mode detected: ");
|
||||
switch(DviMode)
|
||||
{
|
||||
case VHD_DVI_MODE_DVI_D : printf("DVI-D\n");break;
|
||||
case VHD_DVI_MODE_DVI_A : printf("DVI-A\n");break;
|
||||
case VHD_DVI_MODE_ANALOG_COMPONENT_VIDEO : printf("Analog component video\n");break;
|
||||
case VHD_DVI_MODE_HDMI : printf("HDMI\n");break;
|
||||
default : break;
|
||||
}
|
||||
|
||||
/* Disable EDID auto load */
|
||||
Result = VHD_SetStreamProperty(s->StreamHandle,VHD_DVI_SP_DISABLE_EDID_AUTO_LOAD,TRUE);
|
||||
if(Result != VHDERR_NOERROR)
|
||||
goto no_format;
|
||||
|
||||
/* Set the DVI mode of this channel to the detected one */
|
||||
Result = VHD_SetStreamProperty(s->StreamHandle,VHD_DVI_SP_MODE, DviMode);
|
||||
if(Result != VHDERR_NOERROR)
|
||||
goto no_format;
|
||||
|
||||
/* Configure RGBA reception (no color-space conversion) */
|
||||
switch(codec) {
|
||||
case RGB:
|
||||
Packing = VHD_BUFPACK_VIDEO_RGB_32;
|
||||
break;
|
||||
case RGBA:
|
||||
Packing = VHD_BUFPACK_VIDEO_RGBA_32;
|
||||
break;
|
||||
case UYVY:
|
||||
Packing = VHD_BUFPACK_VIDEO_YUV422_8;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown pixel formate entered.\n");
|
||||
goto no_format;
|
||||
}
|
||||
|
||||
Result = VHD_SetStreamProperty(s->StreamHandle,VHD_CORE_SP_BUFFER_PACKING,
|
||||
Packing);
|
||||
|
||||
if(Result != VHDERR_NOERROR) {
|
||||
fprintf(stderr, "Unable to set packing format.\n");
|
||||
goto no_format;
|
||||
}
|
||||
|
||||
if(DviMode == VHD_DVI_MODE_DVI_A)
|
||||
{
|
||||
VHD_DVI_A_STANDARD DviAStd;
|
||||
/* Auto-detection is now available for DVI-A.
|
||||
VHD_DVI_SP_ACTIVE_HEIGHT, VHD_DVI_SP_INTERLACED, VHD_DVI_SP_REFRESH_RATE,
|
||||
VHD_DVI_SP_PIXEL_CLOCK, VHD_DVI_SP_TOTAL_WIDTH, VHD_DVI_SP_TOTAL_HEIGHT,
|
||||
VHD_DVI_SP_H_SYNC, VHD_DVI_SP_H_FRONT_PORCH, VHD_DVI_SP_V_SYNC and
|
||||
VHD_DVI_SP_V_FRONT_PORCH properties are required for DVI-A but
|
||||
the VHD_PresetDviAStreamProperties is a helper function to set all these
|
||||
properties according to a resolution, a refresh rate and a graphic timing
|
||||
standard. Manual setting or overriding of these properties is allowed
|
||||
Resolution, refresh rate and graphic timing standard can be auto-detect
|
||||
with VHD_DetectDviAFormat function */
|
||||
Result = VHD_DetectDviAFormat(s->StreamHandle,&DviAStd,&Width,&Height,&RefreshRate,
|
||||
&Interlaced_B);
|
||||
if(Result == VHDERR_NOERROR)
|
||||
{
|
||||
printf("\nDVI-A format detected: %ux%u @%uHz (%s)\n",Width,Height,RefreshRate
|
||||
,Interlaced_B?"Interlaced":"Progressive");
|
||||
Result = VHD_PresetDviAStreamProperties(s->StreamHandle, DviAStd,Width,Height,
|
||||
RefreshRate,Interlaced_B);
|
||||
}
|
||||
else {
|
||||
printf("ERROR : Cannot detect incoming DVI-A format. Result = 0x%08X\n",
|
||||
Result);
|
||||
goto no_format;
|
||||
}
|
||||
}
|
||||
else if(DviMode == VHD_DVI_MODE_DVI_D)
|
||||
{
|
||||
BOOL Dual_B = FALSE;
|
||||
/* Get auto-detected resolution */
|
||||
Result = VHD_GetStreamProperty(s->StreamHandle,VHD_DVI_SP_ACTIVE_WIDTH,&Width);
|
||||
if(Result == VHDERR_NOERROR)
|
||||
Result = VHD_GetStreamProperty(s->StreamHandle,VHD_DVI_SP_ACTIVE_HEIGHT,&Height);
|
||||
else
|
||||
printf("ERROR : Cannot detect incoming active width from RX0. "
|
||||
"Result = 0x%08X\n", Result);
|
||||
if(Result == VHDERR_NOERROR)
|
||||
Result = VHD_GetStreamProperty(s->StreamHandle,VHD_DVI_SP_INTERLACED,(ULONG*)&Interlaced_B);
|
||||
else
|
||||
printf("ERROR : Cannot detect incoming active height from RX0. "
|
||||
"Result = 0x%08X\n", Result);
|
||||
if(Result == VHDERR_NOERROR)
|
||||
Result = VHD_GetStreamProperty(s->StreamHandle,VHD_DVI_SP_REFRESH_RATE,&RefreshRate);
|
||||
else
|
||||
printf("ERROR : Cannot detect if incoming stream from RX0 is "
|
||||
"interlaced or progressive. Result = 0x%08X\n", Result);
|
||||
if(Result == VHDERR_NOERROR)
|
||||
Result = VHD_GetStreamProperty(s->StreamHandle,VHD_DVI_SP_DUAL_LINK,(ULONG*)&Dual_B);
|
||||
else
|
||||
printf("ERROR : Cannot detect incoming refresh rate from RX0. "
|
||||
"Result = 0x%08X\n", Result);
|
||||
if(Result == VHDERR_NOERROR)
|
||||
printf("\nIncoming graphic resolution : %ux%u @%uHz (%s) %s link\n", Width, Height,RefreshRate, Interlaced_B?"Interlaced":"Progressive",Dual_B?"Dual":"Single");
|
||||
else
|
||||
printf("ERROR : Cannot detect if incoming stream from RX0 is dual or simple link. "
|
||||
"Result = 0x%08X\n", Result);
|
||||
|
||||
if(Result != VHDERR_NOERROR) {
|
||||
goto no_format;
|
||||
}
|
||||
|
||||
/* Configure stream. Only VHD_DVI_SP_ACTIVE_WIDTH, VHD_DVI_SP_ACTIVE_HEIGHT and
|
||||
VHD_DVI_SP_INTERLACED properties are required for DVI-D.
|
||||
VHD_DVI_SP_REFRESH_RATE,VHD_DVI_SP_DUAL_LINK are optional
|
||||
VHD_DVI_SP_PIXEL_CLOCK, VHD_DVI_SP_TOTAL_WIDTH, VHD_DVI_SP_TOTAL_HEIGHT,
|
||||
VHD_DVI_SP_H_SYNC, VHD_DVI_SP_H_FRONT_PORCH, VHD_DVI_SP_V_SYNC and
|
||||
VHD_DVI_SP_V_FRONT_PORCH properties are not applicable for DVI-D */
|
||||
|
||||
VHD_SetStreamProperty(s->StreamHandle,VHD_DVI_SP_ACTIVE_WIDTH,Width);
|
||||
VHD_SetStreamProperty(s->StreamHandle,VHD_DVI_SP_ACTIVE_HEIGHT,Height);
|
||||
VHD_SetStreamProperty(s->StreamHandle,VHD_DVI_SP_INTERLACED,Interlaced_B);
|
||||
VHD_SetStreamProperty(s->StreamHandle,VHD_DVI_SP_REFRESH_RATE,RefreshRate);
|
||||
VHD_SetStreamProperty(s->StreamHandle,VHD_DVI_SP_DUAL_LINK,Dual_B);
|
||||
}
|
||||
else if(DviMode == VHD_DVI_MODE_HDMI || DviMode == VHD_DVI_MODE_ANALOG_COMPONENT_VIDEO)
|
||||
{
|
||||
/* Get auto-detected resolution */
|
||||
Result = VHD_GetStreamProperty(s->StreamHandle,VHD_DVI_SP_ACTIVE_WIDTH,&Width);
|
||||
if(Result == VHDERR_NOERROR)
|
||||
Result = VHD_GetStreamProperty(s->StreamHandle,VHD_DVI_SP_ACTIVE_HEIGHT,&Height);
|
||||
else
|
||||
printf("ERROR : Cannot detect incoming active width from RX0. "
|
||||
"Result = 0x%08X\n", Result);
|
||||
if(Result == VHDERR_NOERROR)
|
||||
Result = VHD_GetStreamProperty(s->StreamHandle,VHD_DVI_SP_INTERLACED,(ULONG*)&Interlaced_B);
|
||||
else
|
||||
printf("ERROR : Cannot detect incoming active height from RX0. "
|
||||
"Result = 0x%08X\n", Result);
|
||||
if(Result == VHDERR_NOERROR)
|
||||
Result = VHD_GetStreamProperty(s->StreamHandle,VHD_DVI_SP_REFRESH_RATE,&RefreshRate);
|
||||
else
|
||||
printf("ERROR : Cannot detect if incoming stream from RX0 is "
|
||||
"interlaced or progressive. Result = 0x%08X\n", Result);
|
||||
if(Result == VHDERR_NOERROR)
|
||||
printf("\nIncoming graphic resolution : %ux%u @%uHz (%s)\n", Width, Height, RefreshRate, Interlaced_B?"Interlaced":"Progressive");
|
||||
else
|
||||
printf("ERROR : Cannot detect incoming refresh rate from RX0. "
|
||||
"Result = 0x%08X\n", Result);
|
||||
|
||||
if(Result != VHDERR_NOERROR) {
|
||||
goto no_format;
|
||||
}
|
||||
|
||||
/* Configure stream. Only VHD_DVI_SP_ACTIVE_WIDTH, VHD_DVI_SP_ACTIVE_HEIGHT and
|
||||
VHD_DVI_SP_INTERLACED properties are required for HDMI and Component
|
||||
VHD_DVI_SP_PIXEL_CLOCK, VHD_DVI_SP_TOTAL_WIDTH, VHD_DVI_SP_TOTAL_HEIGHT,
|
||||
VHD_DVI_SP_H_SYNC, VHD_DVI_SP_H_FRONT_PORCH, VHD_DVI_SP_V_SYNC and
|
||||
VHD_DVI_SP_V_FRONT_PORCH properties are not applicable for DVI-D, HDMI and Component */
|
||||
|
||||
VHD_SetStreamProperty(s->StreamHandle,VHD_DVI_SP_ACTIVE_WIDTH,Width);
|
||||
VHD_SetStreamProperty(s->StreamHandle,VHD_DVI_SP_ACTIVE_HEIGHT,Height);
|
||||
VHD_SetStreamProperty(s->StreamHandle,VHD_DVI_SP_INTERLACED,Interlaced_B);
|
||||
VHD_SetStreamProperty(s->StreamHandle,VHD_DVI_SP_REFRESH_RATE, RefreshRate);
|
||||
}
|
||||
|
||||
gettimeofday(&s->t0, NULL);
|
||||
s->frames = 0;
|
||||
|
||||
struct video_desc desc;
|
||||
desc.color_spec = codec;
|
||||
desc.width = Width;
|
||||
desc.height = Height;
|
||||
desc.fps = RefreshRate;
|
||||
desc.interlacing = Interlaced_B ? INTERLACED_MERGED : PROGRESSIVE;
|
||||
desc.tile_count = 1;
|
||||
|
||||
s->frame = vf_alloc_desc(desc);
|
||||
s->tile = vf_get_tile(s->frame, 0);
|
||||
|
||||
Result = VHD_StartStream(s->StreamHandle);
|
||||
|
||||
if(Result != VHDERR_NOERROR) {
|
||||
goto no_start;
|
||||
}
|
||||
|
||||
return s;
|
||||
|
||||
no_paste:
|
||||
no_start:
|
||||
vf_free(s->frame);
|
||||
no_format:
|
||||
/* Close stream handle */
|
||||
VHD_CloseStreamHandle(s->StreamHandle);
|
||||
no_stream:
|
||||
|
||||
/* Re-establish RX0-TX0 by-pass relay loopthrough */
|
||||
VHD_SetBoardProperty(s->BoardHandle,VHD_CORE_BP_BYPASS_RELAY_0,TRUE);
|
||||
bad_channel:
|
||||
VHD_CloseBoardHandle(s->BoardHandle);
|
||||
error:
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
vidcap_deltacast_dvi_finish(void *state)
|
||||
{
|
||||
UNUSED(state);
|
||||
should_exit = true;
|
||||
}
|
||||
|
||||
void
|
||||
vidcap_deltacast_dvi_done(void *state)
|
||||
{
|
||||
struct vidcap_deltacast_dvi_state *s = (struct vidcap_deltacast_dvi_state *) state;
|
||||
|
||||
assert(s != NULL);
|
||||
|
||||
if(s->SlotHandle)
|
||||
VHD_UnlockSlotHandle(s->SlotHandle);
|
||||
VHD_StopStream(s->StreamHandle);
|
||||
VHD_CloseStreamHandle(s->StreamHandle);
|
||||
/* Re-establish RX0-TX0 by-pass relay loopthrough */
|
||||
VHD_SetBoardProperty(s->BoardHandle,VHD_CORE_BP_BYPASS_RELAY_0,TRUE);
|
||||
VHD_CloseBoardHandle(s->BoardHandle);
|
||||
|
||||
vf_free(s->frame);
|
||||
free(s);
|
||||
}
|
||||
|
||||
struct video_frame *
|
||||
vidcap_deltacast_dvi_grab(void *state, struct audio_frame **audio)
|
||||
{
|
||||
struct vidcap_deltacast_dvi_state *s = (struct vidcap_deltacast_dvi_state *) state;
|
||||
|
||||
ULONG /*SlotsCount, SlotsDropped,*/BufferSize;
|
||||
ULONG Result;
|
||||
BYTE *pBuffer=NULL;
|
||||
|
||||
*audio = NULL;
|
||||
/* Unlock slot */
|
||||
if(s->SlotHandle)
|
||||
VHD_UnlockSlotHandle(s->SlotHandle);
|
||||
Result = VHD_LockSlotHandle(s->StreamHandle,&s->SlotHandle);
|
||||
if (Result != VHDERR_NOERROR) {
|
||||
if (Result != VHDERR_TIMEOUT) {
|
||||
fprintf(stderr, "ERROR : Cannot lock slot on RX0 stream. Result = 0x%08X\n",Result);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Timeout \n");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Result = VHD_GetSlotBuffer(s->SlotHandle, VHD_DVI_BT_VIDEO, &pBuffer, &BufferSize);
|
||||
|
||||
if (Result != VHDERR_NOERROR) {
|
||||
fprintf(stderr, "\nERROR : Cannot get slot buffer. Result = 0x%08X\n",Result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(s->frame->color_spec == RGBA) {
|
||||
vc_copylineRGBA(pBuffer, pBuffer, BufferSize, 16, 8, 0);
|
||||
}
|
||||
|
||||
s->tile->data = (char*) pBuffer;
|
||||
s->tile->data_len = BufferSize;
|
||||
|
||||
/* Print some statistics */
|
||||
/*VHD_GetStreamProperty(s->StreamHandle,VHD_CORE_SP_SLOTS_COUNT,&SlotsCount);
|
||||
VHD_GetStreamProperty(s->StreamHandle,VHD_CORE_SP_SLOTS_DROPPED,&SlotsDropped);
|
||||
printf("%u frames received (%u dropped) \r",SlotsCount,SlotsDropped);*/
|
||||
gettimeofday(&s->t, NULL);
|
||||
double seconds = tv_diff(s->t, s->t0);
|
||||
if (seconds >= 5) {
|
||||
float fps = s->frames / seconds;
|
||||
fprintf(stderr, "[DELTACAST cap.] %d frames in %g seconds = %g FPS\n", s->frames, seconds, fps);
|
||||
s->t0 = s->t;
|
||||
s->frames = 0;
|
||||
}
|
||||
s->frames++;
|
||||
|
||||
return s->frame;
|
||||
}
|
||||
|
||||
62
src/video_capture/deltacast_dvi.h
Normal file
62
src/video_capture/deltacast_dvi.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* FILE: video_capture/deltacast.h
|
||||
* AUTHORS: Martin Benes <martinbenesh@gmail.com>
|
||||
* Lukas Hejtmanek <xhejtman@ics.muni.cz>
|
||||
* Petr Holub <hopet@ics.muni.cz>
|
||||
* Milos Liska <xliska@fi.muni.cz>
|
||||
* Jiri Matela <matela@ics.muni.cz>
|
||||
* Dalibor Matura <255899@mail.muni.cz>
|
||||
* Ian Wesley-Smith <iwsmith@cct.lsu.edu>
|
||||
*
|
||||
* Copyright (c) 2005-2010 CESNET z.s.p.o.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, is permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
*
|
||||
* This product includes software developed by CESNET z.s.p.o.
|
||||
*
|
||||
* 4. Neither the name of the CESNET nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#define VIDCAP_DELTACAST_DVI_ID 0x60253041
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct vidcap_type *vidcap_deltacast_dvi_probe(void);
|
||||
void *vidcap_deltacast_dvi_init(char *fmt, unsigned int flags);
|
||||
void vidcap_deltacast_dvi_finish(void *state);
|
||||
void vidcap_deltacast_dvi_done(void *state);
|
||||
struct video_frame *vidcap_deltacast_dvi_grab(void *state, struct audio_frame **audio);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // END extern "C"
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user