diff --git a/configure.ac b/configure.ac index 137dc3686..c00f3431e 100644 --- a/configure.ac +++ b/configure.ac @@ -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") diff --git a/src/video_capture.c b/src/video_capture.c index b753141f0..a54f3c99c 100644 --- a/src/video_capture.c +++ b/src/video_capture.c @@ -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 { diff --git a/src/video_capture/deltacast_dvi.cpp b/src/video_capture/deltacast_dvi.cpp new file mode 100644 index 000000000..93851307b --- /dev/null +++ b/src/video_capture/deltacast_dvi.cpp @@ -0,0 +1,700 @@ +/* + * FILE: video_capture/deltacast.c + * AUTHORS: Martin Benes + * Lukas Hejtmanek + * Petr Holub + * Milos Liska + * Jiri Matela + * Dalibor Matura <255899@mail.muni.cz> + * Ian Wesley-Smith + * + * 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 +#include +#include +#include +#include +#include +#ifndef WIN32 +#include +#include +#endif +#include +#include + +#ifdef __cplusplus +} // END of extern "C" +#endif + +#include "video_capture/deltacast_dvi.h" + +#include +#include + +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=][:codec=][:edid=]" + "[: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 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 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 may be one of following\n"); + printf("\t\tUYVY (default)\n"); + printf("\t\tRGBA\n"); + printf("\t\tRGB\n"); + + printf("\t 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; +} + diff --git a/src/video_capture/deltacast_dvi.h b/src/video_capture/deltacast_dvi.h new file mode 100644 index 000000000..49b93b5c8 --- /dev/null +++ b/src/video_capture/deltacast_dvi.h @@ -0,0 +1,62 @@ +/* + * FILE: video_capture/deltacast.h + * AUTHORS: Martin Benes + * Lukas Hejtmanek + * Petr Holub + * Milos Liska + * Jiri Matela + * Dalibor Matura <255899@mail.muni.cz> + * Ian Wesley-Smith + * + * 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 +