#include <mil.h>
#include <queue>
#if M_MIL_USE_WINDOWS
#include <windows.h>
#define MosRefresh()
#else
#include <stdlib.h>
#include <ncurses.h>
#include <pthread.h>
#include <X11/Xlib.h>
#define MosPrintf printw
#define MosRefresh refresh
#endif
#define BUFFERING_SIZE_MAX 24
#define PROC_BUFFERING_SIZE_MAX 50
#define SPLASH_SCREEN_IMAGE_FILE M_IMAGE_PATH MIL_TEXT("imaginglogo.mim")
#define SEQUENCE_FILE MIL_TEXT("MilVIOSequence.avi")
#define IMAGE_FILE MIL_TEXT("MilVIOImage")
#define COMPRESSION_Q_FACTOR 50
#define SCALE_FACTOR 3
#define OFFSET_X 10
#define OFFSET_Y 10
#define EVERY_THUMNAIL_IMAGES 10
typedef struct
{
MIL_ID MilSystem;
MIL_ID MilDigitizer;
MIL_ID MilDisplay;
MIL_ID MilImageDispSplashScreen;
MIL_ID MilWindowedDisplay;
MIL_ID MilImageWindowedDisp;
MIL_ID MilImageDispOvr;
MIL_INT CameraPresent;
MIL_INT SaveSequenceToDisk;
MIL_INT SaveAnImageToDisk;
MIL_INT ProcessedImageCount;
double DisplayUpdateTime;
MIL_INT Exit;
} HookDataStruct;
typedef struct
{
MIL_ID MilBufHostYUV16;
double MilBufHostYUV16SizeInMB;
MIL_ID MilBufHostScaled;
double MilBufHostScaledSizeInMB;
bool MilBufHostScaledInUse;
MIL_INT MilBufHostScaledSizeX;
MIL_INT MilBufHostScaledSizeY;
MIL_ID MilCompressedImage;
} BUFFERINGDATASTRUCT;
MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr);
MIL_UINT32 MFTYPE ProcessingThread(void *TPar);
MIL_INT MFTYPE CameraPresentHook(MIL_INT HookType, MIL_ID EventId, void* UserStructPtr);
void OverlayDraw(MIL_ID MilDisplay);
std::queue<BUFFERINGDATASTRUCT> FifoGrabInUse;
std::queue<BUFFERINGDATASTRUCT> FifoGrabFree;
#if M_MIL_USE_WINDOWS
CRITICAL_SECTION FifoLock;
#else
pthread_mutex_t FifoLock;
#endif
int MosMain(void)
{
HookDataStruct UserHookData;
MIL_ID MilApplication = M_NULL;
MIL_ID MilSystem = M_NULL;
MIL_ID MilDigitizer = M_NULL;
MIL_ID MilDisplay = M_NULL;
MIL_ID MilImageDispSplashScreen = M_NULL;
MIL_ID MilImageDispSplashScreenChild = M_NULL;
MIL_ID MilWindowedDisplay = M_NULL;
MIL_ID MilImageWindowedDisp = M_NULL;
MIL_ID MilImageDispOvr = M_NULL;
MIL_ID MilGrabBufferList[BUFFERING_SIZE_MAX] = { 0 };
MIL_ID ProcessingThreadId = M_NULL;
BUFFERINGDATASTRUCT BufferingDataStruct[PROC_BUFFERING_SIZE_MAX];
MIL_INT SaveSequenceToDisk = false, JPEGLicensePresent = false, LicenseModules;
double ProcessFrameRate = 0;
MIL_INT MilGrabBufferListSize = 0;
MIL_INT MilProcListSize = 0;
MIL_INT ProcessFrameMissed = 0, ProcessFrameCount = 0, NbFrames = 0;
MIL_INT i = 0, SizeBand = 0, SizeX = 0, SizeY = 0, SPSizeX = 0, SPSizeY = 0;
MIL_TEXT_CHAR DisplayFormat[512] = {0};
MIL_TEXT_CHAR DigitizerFormat[512] = {0};
MIL_TEXT_CHAR SplashScreenImageFile[512] = {0};
MIL_INT c = 0;
#if M_MIL_USE_WINDOWS
InitializeCriticalSection(&FifoLock);
#else
initscr();
move(0,0);
pthread_mutex_init(&FifoLock, NULL);
#endif
MappAlloc(M_NULL, M_DEFAULT, &MilApplication);
MsysAlloc(M_DEFAULT, M_SYSTEM_VIO , M_DEV0, M_DEFAULT, &MilSystem);
MdigAlloc(MilSystem, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_DEFAULT, &MilDigitizer);
SizeBand = MdigInquire(MilDigitizer, M_SIZE_BAND, M_NULL);
SizeX = MdigInquire(MilDigitizer, M_SIZE_X, M_NULL);
SizeY = MdigInquire(MilDigitizer, M_SIZE_Y, M_NULL);
MdispAlloc(MilSystem, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_AUXILIARY, &MilDisplay);
MdispAlloc(MilSystem, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_WINDOWED, &MilWindowedDisplay);
MappControl(M_DEFAULT, M_ERROR, M_PRINT_DISABLE);
MdispControl(MilWindowedDisplay, M_NO_TEARING, M_ENABLE);
MappControl(M_DEFAULT, M_ERROR, M_PRINT_ENABLE);
MbufAllocColor(MilSystem,
MdispInquire(MilDisplay, M_SIZE_BAND, M_NULL),
MdispInquire(MilDisplay, M_SIZE_X, M_NULL),
MdispInquire(MilDisplay, M_SIZE_Y, M_NULL),
8+M_UNSIGNED,
M_IMAGE + M_DISP + M_PROC,
&MilImageDispSplashScreen);
MbufClear(MilImageDispSplashScreen, 255);
MappControl(M_DEFAULT, M_ERROR, M_PRINT_DISABLE);
MbufAllocColor(MilSystem, SizeBand, SizeX, SizeY, 8L+M_UNSIGNED,
M_IMAGE + M_DISP + (SizeBand == 3? M_YUV16 + M_PACKED:0)
+ M_NON_PAGED + M_VIDEO_MEMORY,
&MilImageWindowedDisp);
MappControl(M_DEFAULT, M_ERROR, M_PRINT_ENABLE);
if(MilImageWindowedDisp == M_NULL)
MbufAllocColor(MilSystem, SizeBand, SizeX, SizeY, 8L+M_UNSIGNED,
M_IMAGE + M_DISP + (SizeBand == 3? M_YUV16 + M_PACKED:0) + M_NON_PAGED,
&MilImageWindowedDisp);
MbufClear(MilImageWindowedDisp, M_COLOR_BLACK);
MosStrcpy(SplashScreenImageFile, 512, SPLASH_SCREEN_IMAGE_FILE);
MappControl(M_DEFAULT, M_ERROR, M_PRINT_DISABLE);
if(MbufDiskInquire(SplashScreenImageFile, M_FILE_FORMAT, M_NULL) == M_INVALID)
{
MosStrcpy(SplashScreenImageFile, 512, MIL_TEXT("..\\"));
MosStrcat(SplashScreenImageFile, 512, SPLASH_SCREEN_IMAGE_FILE);
}
MappControl(M_DEFAULT, M_ERROR, M_PRINT_ENABLE);
MbufDiskInquire(SplashScreenImageFile, M_SIZE_X, &SPSizeX);
MbufDiskInquire(SplashScreenImageFile, M_SIZE_Y, &SPSizeY);
MbufChild2d(MilImageDispSplashScreen,
SizeX/2 - SPSizeX/2,
SizeY/2 - SPSizeY/2,
SPSizeX, SPSizeY,
&MilImageDispSplashScreenChild);
MbufLoad(SplashScreenImageFile, MilImageDispSplashScreenChild);
MbufFree(MilImageDispSplashScreenChild);
MdispSelect(MilDisplay, MilImageDispSplashScreen);
UserHookData.MilSystem = MilSystem;
UserHookData.MilDigitizer = MilDigitizer;
UserHookData.MilDisplay = MilDisplay;
MdispInquire(MilDisplay, M_FORMAT, (MIL_TEXT_PTR)&DisplayFormat);
MdigInquire(MilDigitizer, M_FORMAT, (MIL_TEXT_PTR)&DigitizerFormat);
MosPrintf(MIL_TEXT("This example demonstrates the features of the Matrox Vio.\n\n"));
MosPrintf(MIL_TEXT("The currently selected DCF is:\n%s\n\n"), DigitizerFormat);
MosPrintf(MIL_TEXT("The currently selected VCF is: \n%s\n\n"), DisplayFormat);
MappInquire(M_DEFAULT, M_LICENSE_MODULES, &LicenseModules);
if(LicenseModules & M_LICENSE_JPEGSTD)
{
MosPrintf(MIL_TEXT("\nDo you want to compress and archive the input video? (y/n)\n\n"));
MosRefresh();
if(MosGetch() == 'y')
{
MosPrintf(MIL_TEXT("AVI file: %s\n\n"), SEQUENCE_FILE);
SaveSequenceToDisk = true;
MbufExportSequence(SEQUENCE_FILE, M_DEFAULT, M_NULL, M_NULL, M_DEFAULT, M_OPEN);
}
}
MosRefresh();
for(MilProcListSize = 0; MilProcListSize < PROC_BUFFERING_SIZE_MAX; MilProcListSize++)
{
MbufAllocColor(MilSystem, SizeBand, SizeX, SizeY,
8+M_UNSIGNED,
M_IMAGE + M_NON_PAGED + (SizeBand == 3? M_YUV16 + M_PACKED:0),
&BufferingDataStruct[MilProcListSize].MilBufHostYUV16);
BufferingDataStruct[MilProcListSize].MilBufHostYUV16SizeInMB =
(SizeX * SizeY * (SizeBand == 3? 2:1)) / (1024.0*1024.0);
BufferingDataStruct[MilProcListSize].MilBufHostScaledInUse = false;
BufferingDataStruct[MilProcListSize].MilBufHostScaledSizeInMB =
(((SizeX * SizeY * (SizeBand == 3? 4:1)) / (1024.0*1024.0)))/
(SCALE_FACTOR*SCALE_FACTOR);
BufferingDataStruct[MilProcListSize].MilBufHostScaledSizeX =
(MIL_INT) (SizeX / SCALE_FACTOR);
BufferingDataStruct[MilProcListSize].MilBufHostScaledSizeY =
(MIL_INT) (SizeY / SCALE_FACTOR);
MbufAllocColor(MilSystem, SizeBand,
BufferingDataStruct[MilProcListSize].MilBufHostScaledSizeX,
BufferingDataStruct[MilProcListSize].MilBufHostScaledSizeY,
8+M_UNSIGNED,
M_IMAGE + M_NON_PAGED + (SizeBand == 3 ? M_BGR32 + M_PACKED:0),
&BufferingDataStruct[MilProcListSize].MilBufHostScaled);
if(SaveSequenceToDisk)
{
MbufAllocColor(MilSystem, SizeBand, SizeX, SizeY,
8+M_UNSIGNED,
M_IMAGE + M_COMPRESS + M_JPEG_LOSSY +
(SizeBand == 3 ? M_YUV16+M_PACKED:0),
&BufferingDataStruct[MilProcListSize].MilCompressedImage);
MbufControl(BufferingDataStruct[MilProcListSize].MilCompressedImage, M_Q_FACTOR,
COMPRESSION_Q_FACTOR);
}
else
BufferingDataStruct[MilProcListSize].MilCompressedImage = M_NULL;
FifoGrabFree.push(BufferingDataStruct[MilProcListSize]);
}
if(MappGetError(M_DEFAULT, M_CURRENT,M_NULL) == 0)
{
MappControl(M_DEFAULT, M_ERROR, M_PRINT_DISABLE);
for(MilGrabBufferListSize = 0;
MilGrabBufferListSize < BUFFERING_SIZE_MAX;
MilGrabBufferListSize++)
{
MbufAllocColor(MilSystem, SizeBand, SizeX, SizeY,
8+M_UNSIGNED,
M_IMAGE + M_GRAB + M_ON_BOARD + (SizeBand == 3 ? M_YUV16 + M_PACKED:0),
&MilGrabBufferList[MilGrabBufferListSize]);
if(MilGrabBufferList[MilGrabBufferListSize])
MbufClear(MilGrabBufferList[MilGrabBufferListSize], 0xFF);
else
break;
}
MappControl(M_DEFAULT, M_ERROR, M_PRINT_ENABLE);
MilGrabBufferListSize--;
MbufFree(MilGrabBufferList[MilGrabBufferListSize]);
MdispControl(MilDisplay, M_OVERLAY, M_ENABLE);
MdispInquire(MilDisplay, M_OVERLAY_ID, &MilImageDispOvr);
MdispControl(MilDisplay, M_OVERLAY_CLEAR, M_DEFAULT);
MdispControl(MilDisplay, M_OVERLAY_SHOW, M_ENABLE);
MgraControl(M_DEFAULT, M_BACKGROUND_MODE, M_TRANSPARENT);
MgraColor(M_DEFAULT, M_COLOR_WHITE);
MdispControl(MilDisplay, M_SELECT_VIDEO_SOURCE, MilDigitizer);
MdispControl(MilWindowedDisplay, M_TITLE, M_PTR_TO_DOUBLE(MIL_TEXT("Display Window")));
MdispSelect(MilWindowedDisplay, MilImageWindowedDisp);
UserHookData.ProcessedImageCount = 0;
UserHookData.MilSystem = MilSystem;
UserHookData.MilDigitizer = MilDigitizer;
UserHookData.MilDisplay = MilDisplay;
UserHookData.MilImageDispSplashScreen = MilImageDispSplashScreen;
UserHookData.MilWindowedDisplay = MilWindowedDisplay;
UserHookData.MilImageWindowedDisp = MilImageWindowedDisp;
UserHookData.MilImageDispOvr = MilImageDispOvr;
UserHookData.CameraPresent = true;
UserHookData.SaveSequenceToDisk = SaveSequenceToDisk;
UserHookData.SaveAnImageToDisk = false;
UserHookData.Exit = false;
MdigHookFunction(MilDigitizer, M_CAMERA_PRESENT, CameraPresentHook,
(void *)(&UserHookData));
OverlayDraw(MilImageDispOvr);
MosPrintf(MIL_TEXT("The Matrox Vio is now:\n"));
MosPrintf(MIL_TEXT(" - grabbing in a windowed display\n"));
MosPrintf(MIL_TEXT(" - displaying the input video on the auxiliary display in\n"));
MosPrintf(MIL_TEXT(" minimum-latency pass-through mode with overlay\n"));
if(SaveSequenceToDisk)
MosPrintf(MIL_TEXT(" - compressing and archiving the grabbed video\n"));
MosPrintf(MIL_TEXT("\nPress 's' to save the current image to disk.\n"));
MosPrintf(MIL_TEXT("Press 'q' to stop grabbing.\n\n"));
MosRefresh();
MthrAlloc(M_DEFAULT, M_THREAD, M_DEFAULT, &ProcessingThread, &UserHookData,
&ProcessingThreadId);
MappControl(M_DEFAULT, M_ERROR, M_PRINT_DISABLE);
MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize,
M_START, M_DEFAULT, ProcessingFunction, &UserHookData);
while(!MosKbhit())
{
c = MosGetch();
if(c == 's')
UserHookData.SaveAnImageToDisk = true;
if(c == 'q')
break;
}
#if M_MIL_USE_LINUX
clear();
move(0,0);
MosRefresh();
#endif
UserHookData.Exit = true;
MthrWait(ProcessingThreadId, M_THREAD_END_WAIT, M_NULL);
MthrFree(ProcessingThreadId);
MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize,
M_STOP, M_DEFAULT, ProcessingFunction, &UserHookData);
MappControl(M_DEFAULT, M_ERROR, M_PRINT_ENABLE);
MdigHookFunction(MilDigitizer, M_CAMERA_PRESENT + M_UNHOOK, CameraPresentHook,
(void *)(&UserHookData));
MdigInquire(MilDigitizer, M_PROCESS_FRAME_COUNT, &ProcessFrameCount);
MdigInquire(MilDigitizer, M_PROCESS_FRAME_RATE, &ProcessFrameRate);
MdigInquire(MilDigitizer, M_PROCESS_FRAME_MISSED, &ProcessFrameMissed);
MosPrintf(MIL_TEXT("\n\n%ld frames grabbed at %.1f frames/sec (%.1f ms/frame).\n")
MIL_TEXT("Frame(s) missed:%d .\n"),
ProcessFrameCount, ProcessFrameRate, 1000.0/ProcessFrameRate, ProcessFrameMissed);
MdispSelect(MilWindowedDisplay, M_NULL);
MosPrintf(MIL_TEXT("\nSelect auxiliary display option on exit:\n"));
MosPrintf(MIL_TEXT("1: Splash screen visible (default)\n"));
MosPrintf(MIL_TEXT("2: Live video with overlay\n"));
MosPrintf(MIL_TEXT("3: Live video without overlay\n"));
MosPrintf(MIL_TEXT("4: Auxiliary display disabled\n"));
MosRefresh();
c = MosGetch();
switch(c)
{
case '1':
default:
MdispControl(MilDisplay, M_OVERLAY, M_DISABLE);
MdispControl(MilDisplay, M_OVERLAY_SHOW, M_DISABLE);
MdispControl(MilDisplay, M_SELECT_VIDEO_SOURCE, M_NULL);
MdispControl(MilDisplay, M_AUXILIARY_KEEP_DISPLAY_ALIVE, M_ENABLE);
break;
case '2':
MdispControl(MilDisplay, M_OVERLAY, M_ENABLE);
MdispControl(MilDisplay, M_OVERLAY_SHOW, M_ENABLE);
MdispControl(MilDisplay, M_SELECT_VIDEO_SOURCE, MilDigitizer);
MdispControl(MilDisplay, M_AUXILIARY_KEEP_DISPLAY_ALIVE, M_ENABLE);
break;
case '3':
MdispControl(MilDisplay, M_OVERLAY, M_DISABLE);
MdispControl(MilDisplay, M_OVERLAY_SHOW, M_DISABLE);
MdispControl(MilDisplay, M_SELECT_VIDEO_SOURCE, MilDigitizer);
MdispControl(MilDisplay, M_AUXILIARY_KEEP_DISPLAY_ALIVE, M_ENABLE);
break;
case '4':
MdispControl(MilDisplay, M_SELECT_VIDEO_SOURCE, MilDigitizer);
MdispControl(MilDisplay, M_AUXILIARY_KEEP_DISPLAY_ALIVE, M_DISABLE);
break;
}
}
MthrWait(M_DEFAULT, M_THREAD_WAIT, M_NULL);
if(SaveSequenceToDisk)
MbufExportSequence(SEQUENCE_FILE, M_DEFAULT, M_NULL, M_NULL, ProcessFrameRate, M_CLOSE);
while(MilGrabBufferListSize > 0)
{
MbufFree(MilGrabBufferList[--MilGrabBufferListSize]);
};
while(MilProcListSize>0)
{
MilProcListSize--;
MbufFree(BufferingDataStruct[MilProcListSize].MilBufHostYUV16);
MbufFree(BufferingDataStruct[MilProcListSize].MilBufHostScaled);
MbufFree(BufferingDataStruct[MilProcListSize].MilCompressedImage);
};
if(MilWindowedDisplay)
MdispFree(MilWindowedDisplay);
#if M_MIL_USE_WINDOWS
DeleteCriticalSection(&FifoLock);
#else
pthread_mutex_destroy(&FifoLock);
endwin();
#endif
MdispFree(MilDisplay);
MdigFree(MilDigitizer);
MbufFree(MilImageDispSplashScreen);
MbufFree(MilImageWindowedDisp);
MsysFree(MilSystem);
MappFree(MilApplication);
return 0;
}
MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr)
{
HookDataStruct *UserHookDataPtr = (HookDataStruct *)HookDataPtr;
BUFFERINGDATASTRUCT BufferingDataStruct;
MIL_ID ModifiedBufferId;
double TimeS, TimeE;
MIL_INT CameraPresent = false;
if(UserHookDataPtr->Exit)
return 0;
MdigInquire(UserHookDataPtr->MilDigitizer, M_CAMERA_PRESENT, &CameraPresent);
if((CameraPresent != UserHookDataPtr->CameraPresent))
{
MosSleep(300);
CameraPresentHook(M_CAMERA_PRESENT, 0, HookDataPtr);
}
MdigGetHookInfo(HookId, M_MODIFIED_BUFFER+M_BUFFER_ID, &ModifiedBufferId);
while(FifoGrabFree.empty() && !UserHookDataPtr->Exit)
MosSleep(1);
if(UserHookDataPtr->Exit)
return 0;
if(!UserHookDataPtr->CameraPresent || !CameraPresent)
return 0;
#if M_MIL_USE_WINDOWS
EnterCriticalSection(&FifoLock);
#else
pthread_mutex_lock(&FifoLock);
#endif
BufferingDataStruct = FifoGrabFree.front();
FifoGrabFree.pop();
#if M_MIL_USE_WINDOWS
LeaveCriticalSection(&FifoLock);
#else
pthread_mutex_unlock(&FifoLock);
#endif
MbufCopy(ModifiedBufferId, BufferingDataStruct.MilBufHostYUV16);
MappTimer(M_DEFAULT, M_TIMER_READ, &TimeS);
MbufCopy(ModifiedBufferId, UserHookDataPtr->MilImageWindowedDisp);
MappTimer(M_DEFAULT, M_TIMER_READ, &TimeE);
UserHookDataPtr->DisplayUpdateTime = TimeE - TimeS;
if((UserHookDataPtr->ProcessedImageCount % EVERY_THUMNAIL_IMAGES) == 0)
{
BufferingDataStruct.MilBufHostScaledInUse = true;
MbufTransfer(ModifiedBufferId, BufferingDataStruct.MilBufHostScaled, 0,
M_DEFAULT, M_DEFAULT, M_DEFAULT, M_DEFAULT,
M_DEFAULT, M_DEFAULT,
BufferingDataStruct.MilBufHostScaledSizeX,
BufferingDataStruct.MilBufHostScaledSizeY,
M_DEFAULT, M_COPY + M_SCALE, M_DRIVER_MODE, M_DEFAULT, M_NULL);
}
else
{
BufferingDataStruct.MilBufHostScaledInUse = false;
}
#if M_MIL_USE_WINDOWS
EnterCriticalSection(&FifoLock);
#else
pthread_mutex_lock(&FifoLock);
#endif
FifoGrabInUse.push(BufferingDataStruct);
#if M_MIL_USE_WINDOWS
LeaveCriticalSection(&FifoLock);
#else
pthread_mutex_unlock(&FifoLock);
#endif
return 0;
}
MIL_UINT32 MFTYPE ProcessingThread(void *HookDataPtr)
{
HookDataStruct *UserHookDataPtr = (HookDataStruct *)HookDataPtr;
BUFFERINGDATASTRUCT BufferingDataStruct;
double TimeS, TimeE;
double CompressionTime = 0.0;
static double TumbnailUpdateTime = 0.0;
double DisplayUpdateTime = 0.0;
MIL_INT SavedImageIndex = 0;
while(!UserHookDataPtr->Exit)
{
while(FifoGrabInUse.empty() && !UserHookDataPtr->Exit)
MosSleep(1);
if(UserHookDataPtr->Exit)
break;
UserHookDataPtr->ProcessedImageCount++;
#if M_MIL_USE_WINDOWS
EnterCriticalSection(&FifoLock);
#else
pthread_mutex_lock(&FifoLock);
#endif
BufferingDataStruct = FifoGrabInUse.front();
FifoGrabInUse.pop();
#if M_MIL_USE_WINDOWS
LeaveCriticalSection(&FifoLock);
#else
pthread_mutex_unlock(&FifoLock);
#endif
if(UserHookDataPtr->SaveSequenceToDisk)
{
MappTimer(M_DEFAULT, M_TIMER_READ, &TimeS);
MbufCopy(BufferingDataStruct.MilBufHostYUV16, BufferingDataStruct.MilCompressedImage);
MbufExportSequence(SEQUENCE_FILE, M_DEFAULT,
&BufferingDataStruct.MilCompressedImage,
1, M_DEFAULT,
M_WRITE);
MappTimer(M_DEFAULT, M_TIMER_READ, &TimeE);
CompressionTime = (TimeE - TimeS);
}
if(UserHookDataPtr->SaveAnImageToDisk)
{
MIL_TEXT_CHAR FileName[512];
#if M_MIL_USE_WINDOWS
COORD Coord;
Coord.X = 0; Coord.Y = 24;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Coord);
#endif
MosSprintf(FileName, 512, MIL_TEXT("%s%d.mim"), IMAGE_FILE, SavedImageIndex++);
MbufSave(FileName, BufferingDataStruct.MilBufHostYUV16);
MosPrintf(MIL_TEXT("* Saved image in file: %s"), FileName);
UserHookDataPtr->SaveAnImageToDisk = false;
MosRefresh();
}
if((BufferingDataStruct.MilBufHostScaledInUse) && (UserHookDataPtr->CameraPresent))
{
MappTimer(M_DEFAULT, M_TIMER_READ, &TimeS);
MbufCopyColor2d(BufferingDataStruct.MilBufHostScaled,
UserHookDataPtr->MilImageDispOvr,
M_ALL_BANDS,OFFSET_X,OFFSET_Y,
M_ALL_BANDS,0,0,
BufferingDataStruct.MilBufHostScaledSizeX - (OFFSET_X*2),
BufferingDataStruct.MilBufHostScaledSizeY -(OFFSET_Y*2));
MappTimer(M_DEFAULT, M_TIMER_READ, &TimeE);
TumbnailUpdateTime = (TimeE - TimeS);
}
if(UserHookDataPtr->ProcessedImageCount % 10 == 0)
{
#if M_MIL_USE_WINDOWS
COORD Coord;
Coord.X = 0; Coord.Y = 26;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Coord);
#else
move(11,0);
#endif
MosPrintf(MIL_TEXT("Frames grabbed:\t%d \n"), UserHookDataPtr->ProcessedImageCount);
MosPrintf(MIL_TEXT("Frames missed:\t%d \n\n"),
MdigInquire(UserHookDataPtr->MilDigitizer, M_PROCESS_FRAME_MISSED, M_NULL));
MosPrintf(MIL_TEXT("VGA display update time:\t%3.1f ms \n"),
UserHookDataPtr->DisplayUpdateTime * 1000.0);
MosPrintf(MIL_TEXT("VGA display update rate:\t%3.1f MB/s \n\n"),
BufferingDataStruct.MilBufHostYUV16SizeInMB /
UserHookDataPtr->DisplayUpdateTime);
if(UserHookDataPtr->SaveSequenceToDisk)
{
MosPrintf(MIL_TEXT("Compression time:\t%3.1f ms \n"),
CompressionTime * 1000.0);
MosPrintf(MIL_TEXT("Compression rate:\t%3.1f MB/s \n\n"),
BufferingDataStruct.MilBufHostYUV16SizeInMB / CompressionTime);
}
MosPrintf(MIL_TEXT("Thumbnail update time:\t%3.1f ms \n"),
TumbnailUpdateTime * 1000.0);
MosPrintf(MIL_TEXT("Thumbnail update rate:\t%3.1f MB/s \n\n"),
BufferingDataStruct.MilBufHostScaledSizeInMB / TumbnailUpdateTime);
MosRefresh();
}
#if M_MIL_USE_WINDOWS
EnterCriticalSection(&FifoLock);
#else
pthread_mutex_lock(&FifoLock);
#endif
FifoGrabFree.push(BufferingDataStruct);
#if M_MIL_USE_WINDOWS
LeaveCriticalSection(&FifoLock);
#else
pthread_mutex_unlock(&FifoLock);
#endif
}
return 0;
}
MIL_INT MFTYPE CameraPresentHook(MIL_INT HookType, MIL_ID EventId, void* UserStructPtr)
{
HookDataStruct *UserHookDataPtr = (HookDataStruct *)UserStructPtr;
MIL_ID MilDigitizer = UserHookDataPtr->MilDigitizer;
MIL_ID MilDisplay = UserHookDataPtr->MilDisplay;
MIL_INT CameraPresent = 0;
MdigInquire(MilDigitizer, M_CAMERA_PRESENT, &CameraPresent);
if(CameraPresent == UserHookDataPtr->CameraPresent)
return 0;
#if M_MIL_USE_WINDOWS
COORD Coord;
Coord.X = 0; Coord.Y = 23;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Coord);
#endif
if(CameraPresent)
{
MosPrintf(MIL_TEXT("* Camera is present, displaying video source. \n"));
MdispControl(MilDisplay, M_SELECT_VIDEO_SOURCE, MilDigitizer);
MdispControl(MilDisplay, M_OVERLAY_SHOW, M_ENABLE);
UserHookDataPtr->CameraPresent = true;
}
else
{
UserHookDataPtr->CameraPresent = false;
MosPrintf(MIL_TEXT("* Camera is disconnected, displaying splash screen. \n"));
MdispControl(MilDisplay, M_SELECT_VIDEO_SOURCE, M_NULL);
MdispControl(MilDisplay, M_OVERLAY_SHOW, M_DISABLE);
}
return 0;
}
void OverlayDraw(MIL_ID MilOverlayImage)
{
MIL_INT ImageWidth, ImageHeight;
MIL_INT32 Count;
MIL_TEXT_CHAR chText[80];
ImageWidth = MbufInquire(MilOverlayImage, M_SIZE_X, M_NULL);
ImageHeight = MbufInquire(MilOverlayImage, M_SIZE_Y, M_NULL);
if(ImageWidth > 768)
MgraFont(M_DEFAULT, M_FONT_DEFAULT_LARGE);
MgraControl(M_DEFAULT, M_BACKGROUND_MODE, M_TRANSPARENT);
MgraColor(M_DEFAULT, M_COLOR_WHITE);
MgraText(M_DEFAULT, MilOverlayImage, ImageWidth/9, ImageHeight/5,
MIL_TEXT(" -------------------- "));
MgraText(M_DEFAULT, MilOverlayImage, ImageWidth/9, ImageHeight/5+25,
MIL_TEXT(" - MIL Overlay Text - "));
MgraText(M_DEFAULT, MilOverlayImage, ImageWidth/9, ImageHeight/5+50,
MIL_TEXT(" -------------------- "));
MgraColor(M_DEFAULT, M_COLOR_GREEN);
MgraText(M_DEFAULT, MilOverlayImage, ImageWidth*11/18, ImageHeight/5,
MIL_TEXT(" ---------------------"));
MgraText(M_DEFAULT, MilOverlayImage, ImageWidth*11/18, ImageHeight/5+25,
MIL_TEXT(" - MIL Overlay Text - "));
MgraText(M_DEFAULT, MilOverlayImage, ImageWidth*11/18, ImageHeight/5+50,
MIL_TEXT(" ---------------------"));
#if M_MIL_USE_WINDOWS
MbufControl(MilOverlayImage, M_DC_ALLOC, M_DEFAULT);
HDC hCustomDC = ((HDC)MbufInquire(MilOverlayImage, M_DC_HANDLE, M_NULL));
if (hCustomDC)
{
POINT Hor[2];
POINT Ver[2];
SIZE TxtSz;
RECT Txt;
HPEN hpen = CreatePen(PS_SOLID, 2, RGB(0, 0, 255));
HPEN hpenOld = (HPEN)SelectObject(hCustomDC, hpen);
Hor[0].x = 0;
Hor[0].y = (LONG)ImageHeight/2;
Hor[1].x = (LONG)ImageWidth;
Hor[1].y = (LONG)ImageHeight/2;
Polyline(hCustomDC, Hor, 2);
Ver[0].x = (LONG)ImageWidth/2;
Ver[0].y = 0;
Ver[1].x = (LONG)ImageWidth/2;
Ver[1].y = (LONG)ImageHeight;
Polyline(hCustomDC, Ver, 2);
SelectObject(hCustomDC, hpenOld);
DeleteObject(hpen);
SetBkMode(hCustomDC, TRANSPARENT);
MosStrcpy(chText, 80, MIL_TEXT("GDI Overlay Text"));
Count = (MIL_INT32)MosStrlen(chText);
GetTextExtentPoint(hCustomDC, chText, Count, &TxtSz);
Txt.left = (LONG)ImageWidth*3/18;
Txt.top = (LONG)ImageHeight*17/24;
Txt.right = Txt.left + TxtSz.cx;
Txt.bottom = Txt.top + TxtSz.cy;
SetTextColor(hCustomDC,RGB(255, 0, 0));
DrawText(hCustomDC, chText, Count, &Txt, DT_RIGHT);
Txt.left = (LONG)ImageWidth*12/18;
Txt.top = (LONG)ImageHeight*17/24;
Txt.right = Txt.left + TxtSz.cx;
Txt.bottom = Txt.top + TxtSz.cy;
SetTextColor(hCustomDC, RGB(255, 255, 0));
DrawText(hCustomDC, chText, Count, &Txt, DT_RIGHT);
MbufControl(MilOverlayImage, M_DC_FREE, M_DEFAULT);
MbufControl(MilOverlayImage, M_MODIFIED, M_DEFAULT);
}
#else
move(2,0);
MappControl(M_DEFAULT, M_ERROR, M_PRINT_DISABLE);
MbufControl(MilOverlayImage, M_XPIXMAP_ALLOC, M_COMPENSATION_ENABLE);
MappControl(M_DEFAULT, M_ERROR, M_PRINT_ENABLE);
Pixmap XPixmap = ((Pixmap)MbufInquire(MilOverlayImage, M_XPIXMAP_HANDLE, M_NULL));
if(XPixmap)
{
Display *dpy = XOpenDisplay("");
int screen = DefaultScreen(dpy);
GC gc = XCreateGC(dpy,XPixmap,0,0);
XColor xcolors[3],exact;
XPoint Hor[2];
XPoint Ver[2];
int i;
const char *color_names[] = {
"red",
"yellow",
"blue",
};
for(i=0;i<3;i++)
{
if(!XAllocNamedColor(dpy,DefaultColormap(dpy,screen),color_names[i],
&xcolors[i],&exact))
{
fprintf(stderr, "cant't alloc color %s\n", color_names[i]);
exit (1);
}
}
XSetForeground(dpy,gc, xcolors[2].pixel);
Hor[0].x = 0;
Hor[0].y = ImageHeight/2;
Hor[1].x = ImageWidth;
Hor[1].y = ImageHeight/2;
XDrawLines(dpy,XPixmap,gc,Hor, 2, CoordModeOrigin);
Ver[0].x = ImageWidth/2;
Ver[0].y = 0;
Ver[1].x = ImageWidth/2;
Ver[1].y = ImageHeight;
XDrawLines(dpy,XPixmap,gc,Ver, 2, CoordModeOrigin);
XSetForeground(dpy,gc, xcolors[0].pixel);
MosStrcpy(chText, 80, MIL_TEXT("X Overlay Text"));
Count = MosStrlen(chText);
XDrawString(dpy,XPixmap,gc,
ImageWidth*3/18, ImageHeight*17/24,
chText,Count);
XSetForeground(dpy,gc, xcolors[1].pixel);
XDrawString(dpy,XPixmap,gc,
ImageWidth*12/18, ImageHeight*17/24,
chText,Count);
XSetForeground(dpy,gc, BlackPixel(dpy,screen));
XFlush(dpy);
XFreeGC(dpy,gc);
XCloseDisplay(dpy);
MbufControl(MilOverlayImage, M_XPIXMAP_FREE, M_DEFAULT);
MbufControl(MilOverlayImage, M_MODIFIED, M_DEFAULT);
}
#endif
MgraColor(M_DEFAULT, M_COLOR_WHITE);
MgraFont(M_DEFAULT, M_FONT_DEFAULT_LARGE);
MgraControl(M_DEFAULT, M_BACKGROUND_MODE, M_DEFAULT);
}