#include <mil.h>
#include <vector>
#if M_MIL_USE_WINDOWS
#include <conio.h>
#include <windows.h>
#endif
using namespace std;
#define BUFFERING_SIZE_MAX 20
#define PRINT_DETAILS 0
MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType,
MIL_ID HookId,
void* HookDataPtr);
MIL_ID MilGrabBufferList[BUFFERING_SIZE_MAX] = { 0 };
MIL_INT MilGrabBufferListSize;
struct PacketDelayInfo
{
PacketDelayInfo()
{
BaseFrameRate = 0;
ProcessFrameRate = 0;
DelayInSeconds = 0;
TickFreq = 0;
DelayTickVal = 0;
ProcessFrameCount = 0;
EqualityCounter = 0;
Error = false;
}
MIL_DOUBLE BaseFrameRate;
MIL_DOUBLE ProcessFrameRate;
MIL_DOUBLE DelayInSeconds;
MIL_UINT64 TickFreq;
MIL_INT DelayTickVal;
MIL_INT ProcessFrameCount;
MIL_INT EqualityCounter;
bool Error;
};
struct PacketDelayResults
{
PacketDelayResults()
{
Selection = 0;
}
vector<MIL_STRING> PixelFormats;
vector<MIL_INT> InterPacketDelayInTicks;
vector<MIL_DOUBLE> InterPacketDelayInSec;
vector<MIL_DOUBLE> ReferenceFrameRate;
vector<MIL_DOUBLE> ObtainedFrameRate;
unsigned long Selection;
};
void EnumeratePixelFormats(MIL_ID MilDigitizer, MIL_INT BoardType, PacketDelayResults& Results);
void ApplyPixelFormat(MIL_ID MilDigitizer, PacketDelayResults& Results);
void AllocateAcquisitionBuffers(MIL_ID MilSystem, MIL_ID MilDigitizer, MIL_INT BoardType);
void AcquireReferenceFrameRate(MIL_ID MilDigitizer, PacketDelayInfo& Info, PacketDelayResults& Results);
void FindInterPacketDelay(MIL_ID MilDigitizer, PacketDelayInfo& Info, PacketDelayResults& Results);
void PrintResults(MIL_ID MilDigitizer, PacketDelayInfo& Info, PacketDelayResults& Results);
void GetMilBufferInfoFromPixelFormat(MIL_ID MilDigitizer, MIL_INT& SizeBand,
MIL_INT& BufType, MIL_INT64& Attribute);
bool IsEqual(MIL_DOUBLE A, MIL_DOUBLE B)
{
if(((A+0.1) >= B) && ((A-0.1) <= B))
return true;
else
return false;
}
int MosMain(void)
{
MIL_ID MilApplication;
MIL_ID MilSystem ;
MIL_ID MilDigitizer ;
MIL_INT BoardType = 0;
MIL_UINT NbIterations = 0, i = 0;
PacketDelayInfo PktInfo;
PacketDelayResults Results;
MappAllocDefault(M_DEFAULT, &MilApplication, &MilSystem, M_NULL,
&MilDigitizer, M_NULL);
MsysInquire(MilSystem, M_BOARD_TYPE, &BoardType);
if((BoardType != M_GIGE_VISION))
{
MosPrintf(MIL_TEXT("This example only runs on GigE Vision systems.\n"));
MappFreeDefault(MilApplication, MilSystem, M_NULL, MilDigitizer, M_NULL);
return 0;
}
MdigInquire(MilDigitizer, M_GC_COUNTER_TICK_FREQUENCY, &PktInfo.TickFreq);
if(PktInfo.TickFreq == 0)
{
MosPrintf(MIL_TEXT("Error, camera does not support inter-packet delay.\n"));
MappFreeDefault(MilApplication, MilSystem, M_NULL, MilDigitizer, M_NULL);
return 0;
}
MosPrintf(MIL_TEXT("\nThis example shows how to calculate inter-packet\n"));
MosPrintf(MIL_TEXT("delay for your GigE Vision camera.\n\n"));
MosPrintf(MIL_TEXT("Inter-packet delay is used to spread packet transmission\n"));
MosPrintf(MIL_TEXT("over the length of a frame. This is done to minimize the chance\n"));
MosPrintf(MIL_TEXT("of FIFO overruns inside your Gigabit Ethernet controller.\n"));
MosPrintf(MIL_TEXT("Press <Enter> to continue.\n\n\n"));
MosGetch();
EnumeratePixelFormats(MilDigitizer, BoardType, Results);
if(Results.Selection == Results.PixelFormats.size())
{
NbIterations = Results.PixelFormats.size();
Results.Selection = 0;
}
else
NbIterations = 1;
while(NbIterations--)
{
memset(&PktInfo, 0, sizeof(PacketDelayInfo));
MdigInquire(MilDigitizer, M_GC_COUNTER_TICK_FREQUENCY, &PktInfo.TickFreq);
ApplyPixelFormat(MilDigitizer, Results);
AllocateAcquisitionBuffers(MilSystem, MilDigitizer, BoardType);
MosPrintf(MIL_TEXT("\n\nCalculating inter-packet delay for %s.\n\n"), Results.PixelFormats[Results.Selection].c_str());
AcquireReferenceFrameRate(MilDigitizer, PktInfo, Results);
FindInterPacketDelay(MilDigitizer, PktInfo, Results);
while(MilGrabBufferListSize > 0)
MbufFree(MilGrabBufferList[--MilGrabBufferListSize]);
Results.Selection++;
}
PrintResults(MilDigitizer, PktInfo, Results);
MosPrintf(MIL_TEXT("Press <Enter> to quit.\n\n\n"));
MosGetch();
MdigControl(MilDigitizer, M_GC_INTER_PACKET_DELAY, 0);
MappFreeDefault(MilApplication, MilSystem, M_NULL, MilDigitizer, M_NULL);
return 0;
}
void EnumeratePixelFormats(MIL_ID MilDigitizer, MIL_INT BoardType, PacketDelayResults& Results)
{
long SpreadFactor = 0;
MIL_INT64 PixFmt = 0;
Results.Selection = -1;
MIL_INT Count = 0;
MdigInquireFeature(MilDigitizer, M_FEATURE_ENUM_ENTRY_COUNT, MIL_TEXT("PixelFormat"), M_TYPE_MIL_INT, &Count);
if(Count)
{
bool Done = false;
Results.InterPacketDelayInTicks.assign(Count, 0);
Results.InterPacketDelayInSec.assign(Count, 0.0);
Results.ReferenceFrameRate.assign(Count, 0.0);
Results.ObtainedFrameRate.assign(Count, 0.0);
MosPrintf(MIL_TEXT("Your camera supports the following pixel formats:\n"));
for (MIL_INT i = 0; i < Count; i++)
{
MIL_INT64 AccessMode = 0;
MIL_STRING PixelFormat;
MdigInquireFeature(MilDigitizer, M_FEATURE_ENUM_ENTRY_NAME + i, MIL_TEXT("PixelFormat"), M_TYPE_STRING, PixelFormat);
MdigInquireFeature(MilDigitizer, M_FEATURE_ENUM_ENTRY_VALUE + i, MIL_TEXT("PixelFormat"), M_TYPE_INT64, &PixFmt);
MdigInquireFeature(MilDigitizer, M_FEATURE_ENUM_ENTRY_ACCESS_MODE + i, MIL_TEXT("PixelFormat"), M_TYPE_INT64, &AccessMode);
if (M_FEATURE_IS_AVAILABLE(AccessMode) && (PixFmt & PFNC_CUSTOM) != PFNC_CUSTOM)
{
MIL_INT SizeBand = 0, BufType = 0;
MIL_INT64 Attribute = 0;
MappControl(M_ERROR, M_PRINT_DISABLE);
MdigControlFeature(MilDigitizer, M_FEATURE_VALUE, MIL_TEXT("PixelFormat"), M_TYPE_STRING, PixelFormat);
GetMilBufferInfoFromPixelFormat(MilDigitizer, SizeBand, BufType, Attribute);
if(SizeBand && BufType && Attribute)
{
Results.PixelFormats.push_back(PixelFormat);
MosPrintf(MIL_TEXT("%d %s\n"), (int)(Results.PixelFormats.size() - 1), PixelFormat.c_str());
}
MappControl(M_ERROR, M_PRINT_ENABLE);
}
}
if(Results.PixelFormats.size() > 1)
MosPrintf(MIL_TEXT("%d All\n"), (int)Results.PixelFormats.size());
if(Results.PixelFormats.size() > 1)
{
do
{
MosPrintf(MIL_TEXT("\nPlease select the pixel format that you want use for inter-packet delay\n"));
MosPrintf(MIL_TEXT("calculation (0-%d): "), (int)Results.PixelFormats.size());
#if M_MIL_USE_WINDOWS
scanf_s("%d-", &(Results.Selection));
#else
scanf("%ld-", &(Results.Selection));
#endif
if(Results.Selection >= 0 && Results.Selection <= Results.PixelFormats.size())
Done = true;
else
MosPrintf(MIL_TEXT("Invalid selection, please try again\n."));
}
while(!Done);
MosPrintf(MIL_TEXT("\n%s selected\n\n"),
Results.Selection < Results.PixelFormats.size() ? Results.PixelFormats[Results.Selection].c_str() : MIL_TEXT("All"));
}
else
Results.Selection = 0;
}
}
void ApplyPixelFormat(MIL_ID MilDigitizer, PacketDelayResults& Results)
{
MIL_INT64 AccessMode = 0;
MdigInquireFeature(MilDigitizer, M_FEATURE_ACCESS_MODE, MIL_TEXT("PixelFormat"), M_TYPE_INT64, &AccessMode);
while (M_FEATURE_IS_WRITABLE(AccessMode) == M_FALSE)
{
MdigInquireFeature(MilDigitizer, M_FEATURE_ACCESS_MODE, MIL_TEXT("PixelFormat"), M_TYPE_INT64, &AccessMode);
MosSleep(250);
}
MdigControlFeature(MilDigitizer, M_FEATURE_VALUE, MIL_TEXT("PixelFormat"), M_TYPE_STRING, Results.PixelFormats[Results.Selection]);
}
void AllocateAcquisitionBuffers(MIL_ID MilSystem, MIL_ID MilDigitizer, MIL_INT BoardType)
{
MIL_INT SizeBand = 1;
MIL_INT BufType = 8+M_UNSIGNED;
MIL_INT64 AdditionalAttributes = 0;
if(BoardType == M_GIGE_VISION)
{
MdigControl(MilDigitizer, M_GC_PIXEL_FORMAT_SWITCHING, M_DISABLE);
MdigControl(MilDigitizer, M_BAYER_CONVERSION, M_DISABLE);
GetMilBufferInfoFromPixelFormat(MilDigitizer, SizeBand, BufType, AdditionalAttributes);
}
MappControl(M_DEFAULT, M_ERROR, M_PRINT_DISABLE);
for(MilGrabBufferListSize = 0;
MilGrabBufferListSize<BUFFERING_SIZE_MAX; MilGrabBufferListSize++)
{
MbufAllocColor(MilSystem,
SizeBand,
MdigInquire(MilDigitizer, M_SIZE_X, M_NULL),
MdigInquire(MilDigitizer, M_SIZE_Y, M_NULL),
BufType,
M_IMAGE+M_GRAB+M_PROC+AdditionalAttributes,
&MilGrabBufferList[MilGrabBufferListSize]);
if (MilGrabBufferList[MilGrabBufferListSize])
{
MbufClear(MilGrabBufferList[MilGrabBufferListSize], 0xFF);
}
else
break;
}
MappControl(M_DEFAULT, M_ERROR, M_PRINT_ENABLE);
}
void AcquireReferenceFrameRate(MIL_ID MilDigitizer, PacketDelayInfo& Info, PacketDelayResults& Results)
{
MdigControl(MilDigitizer, M_GC_INTER_PACKET_DELAY, 0);
MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize,
M_SEQUENCE+M_COUNT(BUFFERING_SIZE_MAX), M_DEFAULT, ProcessingFunction, M_NULL);
MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize,
M_STOP, M_DEFAULT, ProcessingFunction, M_NULL);
MdigInquire(MilDigitizer, M_PROCESS_FRAME_RATE, &Info.BaseFrameRate);
Results.ReferenceFrameRate[Results.Selection] = Info.BaseFrameRate;
MdigInquire(MilDigitizer, M_GC_THEORETICAL_INTER_PACKET_DELAY, &Info.DelayInSeconds);
Info.DelayTickVal = (MIL_UINT32)(Info.DelayInSeconds * Info.TickFreq);
}
void FindInterPacketDelay(MIL_ID MilDigitizer, PacketDelayInfo& Info, PacketDelayResults& Results)
{
bool Done = false;
#if PRINT_DETAILS
MosPrintf(MIL_TEXT("Reference frame-rate used: %.2f\n\n"), Info.BaseFrameRate);
#endif
while(!Done)
{
MdigControl(MilDigitizer, M_GC_INTER_PACKET_DELAY, Info.DelayTickVal);
MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize,
M_SEQUENCE+M_COUNT(BUFFERING_SIZE_MAX), M_DEFAULT, ProcessingFunction, M_NULL);
MdigInquire(MilDigitizer, M_PROCESS_FRAME_RATE, &Info.ProcessFrameRate);
MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize,
M_STOP, M_DEFAULT, ProcessingFunction, M_NULL);
#if PRINT_DETAILS
MosPrintf(MIL_TEXT("%Programming delay of %d ticks; frame-rate obtained: %.2f\r"),
(int)Info.DelayTickVal, Info.ProcessFrameRate);
#else
MosPrintf(MIL_TEXT("."));
#endif
if(IsEqual(Info.BaseFrameRate, Info.ProcessFrameRate))
{
Info.EqualityCounter++;
if(Info.DelayTickVal == 0)
{
Info.DelayInSeconds = 0.0;
Info.Error = true;
Done = true;
}
else if(Info.EqualityCounter == 3)
{
Done = true;
Info.DelayInSeconds -= (Info.DelayInSeconds * 15.0 / 100.0);
if(Info.DelayInSeconds <= 0.0)
Info.DelayInSeconds = 0.0;
Info.DelayTickVal = (MIL_UINT32)(Info.DelayInSeconds * Info.TickFreq);
MdigControl(MilDigitizer, M_GC_INTER_PACKET_DELAY, Info.DelayTickVal);
}
else
{
Info.DelayInSeconds -= (Info.DelayInSeconds / 50.0);
Info.DelayTickVal = (MIL_UINT32)(Info.DelayInSeconds * Info.TickFreq);
}
}
else
{
Info.EqualityCounter = 0;
Info.DelayInSeconds -= (Info.DelayInSeconds / 10.0);
Info.DelayTickVal = (MIL_UINT32)(Info.DelayInSeconds * Info.TickFreq);
if(Info.DelayTickVal == 0)
{
Info.DelayInSeconds = 0.0;
Info.Error = true;
Done = true;
}
else if(Info.DelayInSeconds <= 0.0)
{
Info.DelayInSeconds = 0.0;
Done = true;
}
}
MosSleep(500);
}
if(Info.Error == false)
{
Results.InterPacketDelayInTicks[Results.Selection] = Info.DelayTickVal;
Results.InterPacketDelayInSec[Results.Selection] = Info.DelayInSeconds;
Results.ObtainedFrameRate[Results.Selection] = Info.ProcessFrameRate;
}
}
void PrintResults(MIL_ID MilDigitizer, PacketDelayInfo& Info, PacketDelayResults& Results)
{
MIL_STRING Model, Vendor;
MIL_INT PacketSize = 0;
MdigInquire(MilDigitizer, M_CAMERA_VENDOR, Vendor);
MdigInquire(MilDigitizer, M_CAMERA_MODEL, Model);
MdigInquire(MilDigitizer, M_GC_PACKET_SIZE, &PacketSize);
#if M_MIL_USE_WINDOWS
system("cls");
#endif
MosPrintf(MIL_TEXT("Inter-packet delay report summary for %s %s:\n\n"), Vendor.c_str(), Model.c_str());
MosPrintf(MIL_TEXT("Camera parameters:\n"));
MosPrintf(MIL_TEXT("Camera SizeX: %lld\n"), (long long)(MdigInquire(MilDigitizer, M_SIZE_X, M_NULL)));
MosPrintf(MIL_TEXT("Camera SizeY: %lld\n"), (long long)(MdigInquire(MilDigitizer, M_SIZE_Y, M_NULL)));
MosPrintf(MIL_TEXT("Camera Packet size: %d\n\n"), (int)PacketSize);
for (size_t i = 0; i < Results.PixelFormats.size(); i++)
{
MosPrintf(MIL_TEXT("Camera Pixel format: %s\n"), Results.PixelFormats[i].c_str());
MosPrintf(MIL_TEXT("Inter-packet delay of %d ticks (%.3f usec) calculated.\n"),
(int)Results.InterPacketDelayInTicks[i], Results.InterPacketDelayInSec[i]*1e6);
MosPrintf(MIL_TEXT("Reference frame rate: %.1f\n"), Results.ReferenceFrameRate[i]);
MosPrintf(MIL_TEXT("Obtained frame rate: %.1f\n"), Results.ObtainedFrameRate[i]);
MosPrintf(MIL_TEXT("----------------------------------------------------------\n"));
}
MosPrintf(MIL_TEXT("\nPrinted inter-packet delay results are valid only for ")
MIL_TEXT("the above parameters\n"));
}
MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType,
MIL_ID HookId,
void* HookDataPtr)
{
MIL_ID ModifiedBufferId;
MdigGetHookInfo(HookId, M_MODIFIED_BUFFER+M_BUFFER_ID, &ModifiedBufferId);
return 0;
}
void GetMilBufferInfoFromPixelFormat(MIL_ID MilDigitizer, MIL_INT& SizeBand,
MIL_INT& BufType, MIL_INT64& Attribute)
{
MdigInquire(MilDigitizer, M_SIZE_BAND, &SizeBand);
MdigInquire(MilDigitizer, M_TYPE, &BufType);
MdigInquire(MilDigitizer, M_SOURCE_DATA_FORMAT, &Attribute);
}