#include <mil.h>
#define BUFFERING_SIZE_MAX 20
#define SEQUENCE_FILE M_TEMP_DIR MIL_TEXT("SeqProcess.mp4")
#define REMOTE_SEQUENCE_FILE MIL_TEXT("remote:
enum ProcessingHookOperation
{
DISPLAY,
ENCODE,
};
MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr);
typedef struct
{
MIL_ID MilDigitizer;
MIL_ID MilImageDisp;
MIL_ID MilSeqContext;
MIL_INT ProcessedImageCount;
ProcessingHookOperation ProcessingOperation;
} ProcessingHookDataStruct;
MIL_INT MFTYPE FrameEncodingEndFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr);
MIL_INT MFTYPE FrameDecodingEndFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr);
MIL_INT CheckMseqProcessError(MIL_ID MilApplication, MIL_ID MilCompressContext);
MIL_INT PrintMilErrorMessage(MIL_ID MilApplication);
typedef struct
{
MIL_INT EncodedImageCount;
MIL_ID DecompressContextID;
} EncodingFrameEndHookDataStruct;
typedef struct
{
MIL_INT DecodedImageCount;
MIL_ID MilImageDisp;
} DecodingFrameEndHookDataStruct;
int MosMain(void)
{
MIL_ID MilApplication;
MIL_ID MilRemoteApplication;
MIL_ID MilSystem;
MIL_ID MilDigitizer;
MIL_ID MilDisplay;
MIL_ID MilImageDisp;
MIL_ID MilGrabBufferList[BUFFERING_SIZE_MAX] = { 0 };
MIL_ID MilCompressContext;
MIL_ID MilDecompressContext;
MIL_INT LicenseModules = 0;
MIL_INT MilSystemLocation;
MIL_INT MilGrabBufferListSize;
MIL_INT ProcessFrameCount = 0;
MIL_INT NbFrames = 0, n = 0;
MIL_DOUBLE EncodingDesiredFrameRate = 0.0;
MIL_DOUBLE ProcessFrameRate = 0.0;
MIL_INT SeqProcessFilePathSize;
MIL_TEXT_PTR SeqProcessFilePath = M_NULL;
ProcessingHookDataStruct ProcessingUserHookData;
EncodingFrameEndHookDataStruct EncodingFrameEndUserHookData;
DecodingFrameEndHookDataStruct DecodingFrameEndUserHookData;
MIL_INT SeqSystemType = M_NULL;
MappAllocDefault(M_DEFAULT, &MilApplication, &MilSystem, &MilDisplay,
&MilDigitizer, &MilImageDisp);
MsysInquire(MilSystem, M_OWNER_APPLICATION, &MilRemoteApplication);
MilSystemLocation = MsysInquire(MilSystem, M_LOCATION, M_NULL);
if (MappInquire(MilRemoteApplication, M_PLATFORM_OS_TYPE, M_NULL) != M_OS_WINDOWS)
{
if (MilSystemLocation == M_REMOTE)
MosPrintf(MIL_TEXT("The Distributed MIL server must run on a Windows system.\n"));
else
MosPrintf(MIL_TEXT("This example only works with a Windows system.\n"));
MosPrintf(MIL_TEXT("Press <Enter> to end.\n"));
MosGetch();
MappFreeDefault(MilApplication, MilSystem, MilDisplay, MilDigitizer, MilImageDisp);
return 0;
}
MappInquire(MilRemoteApplication, M_LICENSE_MODULES, &LicenseModules);
if (!(LicenseModules & (M_LICENSE_JPEGSTD)))
{
MosPrintf(MIL_TEXT("Need a Compression/Decompression license to run this example.\n"));
MosPrintf(MIL_TEXT("Press <Enter> to end.\n"));
MosGetch();
MappFreeDefault(MilApplication, MilSystem, MilDisplay, MilDigitizer, MilImageDisp);
return 0;
}
MappControl(M_DEFAULT, M_ERROR, M_PRINT_DISABLE);
for (MilGrabBufferListSize = 0;
MilGrabBufferListSize < BUFFERING_SIZE_MAX;
MilGrabBufferListSize++
)
{
MbufAllocColor(MilSystem, MdigInquire(MilDigitizer, M_SIZE_BAND, M_NULL),
MdigInquire(MilDigitizer, M_SIZE_X, M_NULL),
MdigInquire(MilDigitizer, M_SIZE_Y, M_NULL),
8 + M_UNSIGNED, M_IMAGE + M_GRAB + M_PROC,
&MilGrabBufferList[MilGrabBufferListSize]
);
if (MilGrabBufferList[MilGrabBufferListSize])
{
MbufClear(MilGrabBufferList[MilGrabBufferListSize], 0xFF);
}
else
break;
}
MappControl(M_DEFAULT, M_ERROR, M_PRINT_ENABLE);
for (n = 0; n < 2 && MilGrabBufferListSize; n++)
{
MilGrabBufferListSize--;
MbufFree(MilGrabBufferList[MilGrabBufferListSize]);
}
if (MilGrabBufferListSize == 0)
{
MosPrintf(MIL_TEXT("!!! No grab buffers have been allocated. Need to set more Non-Paged Memory. !!!\n"));
MappFreeDefault(MilApplication, MilSystem, MilDisplay, MilDigitizer, MilImageDisp);
MosPrintf(MIL_TEXT("Press <Enter> to end.\n"));
MosGetch();
return 1;
}
ProcessingUserHookData.MilDigitizer = MilDigitizer;
ProcessingUserHookData.MilSeqContext = M_NULL;
ProcessingUserHookData.MilImageDisp = MilImageDisp;
ProcessingUserHookData.ProcessedImageCount = 0;
ProcessingUserHookData.ProcessingOperation = DISPLAY;
MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize, M_START, M_DEFAULT, ProcessingFunction, &ProcessingUserHookData);
MosPrintf(MIL_TEXT("\nH.264 IMAGE SEQUENCE COMPRESSION.\n"));
MosPrintf(MIL_TEXT("---------------------------------\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> to start compression.\r"));
MosGetch();
MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize, M_STOP, M_DEFAULT, ProcessingFunction, &ProcessingUserHookData);
MdigInquire(MilDigitizer, M_PROCESS_FRAME_RATE, &EncodingDesiredFrameRate);
MosPrintf(MIL_TEXT("Grabbing frames at %.2f frames/sec.\n"), EncodingDesiredFrameRate);
MseqAlloc(MilSystem, M_DEFAULT, M_SEQ_COMPRESS, M_DEFAULT,
M_DEFAULT, &MilCompressContext);
MseqDefine(MilCompressContext, M_SEQ_OUTPUT(0) + M_SEQ_DEST(0), M_FILE,
(MilSystemLocation != M_REMOTE ? SEQUENCE_FILE : REMOTE_SEQUENCE_FILE),
M_FILE_FORMAT_MP4);
MseqControl(MilCompressContext, M_CONTEXT, M_STREAM_BIT_RATE_MODE, M_VARIABLE);
MseqControl(MilCompressContext, M_CONTEXT, M_STREAM_BIT_RATE, 5000);
MseqControl(MilCompressContext, M_CONTEXT, M_STREAM_BIT_RATE_MAX, 5000);
if (EncodingDesiredFrameRate != 0)
MseqControl(MilCompressContext, M_CONTEXT, M_STREAM_FRAME_RATE, EncodingDesiredFrameRate);
MseqControl(MilCompressContext, M_CONTEXT, M_STREAM_FRAME_RATE_MODE, M_VARIABLE);
MseqControl(MilCompressContext, M_CONTEXT, M_STREAM_QUALITY, 100);
MseqControl(MilCompressContext, M_CONTEXT, M_STREAM_PROFILE, M_PROFILE_HIGH);
MseqControl(MilCompressContext, M_CONTEXT, M_STREAM_LEVEL, M_LEVEL_4_2);
MseqControl(MilCompressContext, M_CONTEXT, M_STREAM_GROUP_OF_PICTURE_SIZE, 30);
EncodingFrameEndUserHookData.EncodedImageCount = 0;
MseqHookFunction(MilCompressContext, M_FRAME_END, FrameEncodingEndFunction,
&EncodingFrameEndUserHookData);
MseqControl(MilCompressContext, M_CONTEXT, M_BUFFER_SAMPLE, MilGrabBufferList[0]);
MappControl(M_ERROR, M_PRINT_DISABLE);
MseqProcess(MilCompressContext, M_START, M_ASYNCHRONOUS);
if (CheckMseqProcessError(MilApplication, MilCompressContext))
{
MseqProcess(MilCompressContext, M_STOP, M_NULL);
MIL_INT SourceSizeX, SourceSizeY;
MIL_DOUBLE SourceFPS;
MdigInquire(MilDigitizer, M_SIZE_X, &SourceSizeX);
MdigInquire(MilDigitizer, M_SIZE_Y, &SourceSizeY);
MdigInquire(MilDigitizer, M_PROCESS_FRAME_RATE, &SourceFPS);
MosPrintf(MIL_TEXT("Unable to perform H.264 encoding with the current input source of\n"));
MosPrintf(MIL_TEXT("%d X %d @ %.2f fps.\n"), (int)SourceSizeX, (int)SourceSizeY, SourceFPS);
MosPrintf(MIL_TEXT("\nExample parameters are optimized for sources of\n"));
MosPrintf(MIL_TEXT("1920 x 1080 @ 60 fps.\n"));
MosPrintf(MIL_TEXT("\nYou can try changing encoding parameters to better match your source.\n\n"));
MosPrintf(MIL_TEXT("Press <Enter> to end.\n"));
MosGetch();
while (MilGrabBufferListSize > 0)
{
MbufFree(MilGrabBufferList[--MilGrabBufferListSize]);
MilGrabBufferList[MilGrabBufferListSize] = M_NULL;
}
if (SeqProcessFilePath)
{
delete[] SeqProcessFilePath;
SeqProcessFilePath = M_NULL;
}
MseqFree(MilCompressContext);
MappFreeDefault(MilApplication, MilSystem, MilDisplay, MilDigitizer, MilImageDisp);
return 0;
}
MappControl(M_ERROR, M_PRINT_ENABLE);
MosPrintf(MIL_TEXT("Live image capture and compression to file using "));
MseqInquire(MilCompressContext, M_CONTEXT, M_CODEC_TYPE, &SeqSystemType);
if (SeqSystemType == M_HARDWARE + M_QSV)
MosPrintf(MIL_TEXT("Hardware acceleration.\n"));
else
MosPrintf(MIL_TEXT("Software implementation.\n"));
ProcessingUserHookData.MilSeqContext = MilCompressContext;
ProcessingUserHookData.ProcessedImageCount = 0;
ProcessingUserHookData.ProcessingOperation = ENCODE;
MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize, M_START, M_DEFAULT, ProcessingFunction, &ProcessingUserHookData);
MosPrintf(MIL_TEXT("Press <Enter> to stop.\n\n"));
MosGetch();
MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize,
M_STOP + M_WAIT, M_DEFAULT, ProcessingFunction, &ProcessingUserHookData);
MseqProcess(MilCompressContext, M_STOP, M_WAIT);
MdigInquire(MilDigitizer, M_PROCESS_FRAME_COUNT, &ProcessFrameCount);
MdigInquire(MilDigitizer, M_PROCESS_FRAME_RATE, &ProcessFrameRate);
MosPrintf(MIL_TEXT("%d frames encoded at %.2f frames/sec (%.1f ms/frame).\n\n"),
(int)ProcessFrameCount, ProcessFrameRate, 1000.0 / ProcessFrameRate);
MseqInquire(MilCompressContext, M_SEQ_OUTPUT(0) + M_SEQ_DEST(0), M_STREAM_FILE_NAME_SIZE, &SeqProcessFilePathSize);
SeqProcessFilePath = new MIL_TEXT_CHAR[SeqProcessFilePathSize];
MseqInquire(MilCompressContext, M_SEQ_OUTPUT(0) + M_SEQ_DEST(0), M_STREAM_FILE_NAME, SeqProcessFilePath);
MosPrintf(MIL_TEXT("The video sequence file was written to:\n%s.\n\n"), SeqProcessFilePath);
MosPrintf(MIL_TEXT("It can be played back using any compatible video player.\n"));
while (MilGrabBufferListSize > 0)
{
MbufFree(MilGrabBufferList[--MilGrabBufferListSize]);
MilGrabBufferList[MilGrabBufferListSize] = M_NULL;
}
if (SeqProcessFilePath)
{
delete[] SeqProcessFilePath;
SeqProcessFilePath = M_NULL;
}
MseqFree(MilCompressContext);
MosPrintf(MIL_TEXT("Press <Enter> to replay encoded sequence.\n"));
MosGetch();
MseqAlloc(MilSystem, M_DEFAULT, M_SEQ_DECOMPRESS, M_DEFAULT,
M_DEFAULT, &MilDecompressContext);
MseqDefine(MilDecompressContext, M_SEQ_INPUT(0), M_FILE,
(MilSystemLocation != M_REMOTE ? SEQUENCE_FILE : REMOTE_SEQUENCE_FILE),
M_FILE_FORMAT_MP4);
MIL_DOUBLE outputFrameRate = 0.0;
MseqInquire(MilDecompressContext, M_SEQ_INPUT(0), M_STREAM_FRAME_RATE, &outputFrameRate);
MosPrintf(MIL_TEXT("\nReplaying file at %.2f frames/second.\n"), outputFrameRate);
DecodingFrameEndUserHookData.DecodedImageCount = 0;
DecodingFrameEndUserHookData.MilImageDisp = MilImageDisp;
MseqHookFunction(MilDecompressContext, M_FRAME_END, FrameDecodingEndFunction,
&DecodingFrameEndUserHookData);
MseqProcess(MilDecompressContext, M_START, M_ASYNCHRONOUS);
MosPrintf(MIL_TEXT("Press <Enter> to stop.\n\n"));
MosGetch();
MseqProcess(MilDecompressContext, M_STOP, M_NULL);
MseqFree(MilDecompressContext);
MosPrintf(MIL_TEXT("Press <Enter> to end.\n"));
MosGetch();
MappFreeDefault(MilApplication, MilSystem, MilDisplay, MilDigitizer, MilImageDisp);
return 0;
}
#define STRING_LENGTH_MAX 20
#define STRING_POS_X 20
#define STRING_POS_Y 20
MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr)
{
ProcessingHookDataStruct *UserHookDataPtr = (ProcessingHookDataStruct *)HookDataPtr;
MIL_ID ModifiedBufferId;
MIL_TEXT_CHAR Text[STRING_LENGTH_MAX] = { MIL_TEXT('\0'), };
MdigGetHookInfo(HookId, M_MODIFIED_BUFFER + M_BUFFER_ID, &ModifiedBufferId);
switch (UserHookDataPtr->ProcessingOperation)
{
case DISPLAY:
MbufCopy(ModifiedBufferId, UserHookDataPtr->MilImageDisp);
break;
case ENCODE:
UserHookDataPtr->ProcessedImageCount++;
MosPrintf(MIL_TEXT("Processing frame #%d.\r"), (int)UserHookDataPtr->ProcessedImageCount);
MosSprintf(Text, STRING_LENGTH_MAX, MIL_TEXT("%d"), (int)UserHookDataPtr->ProcessedImageCount);
MgraText(M_DEFAULT, ModifiedBufferId, STRING_POS_X, STRING_POS_Y, Text);
MseqFeed(UserHookDataPtr->MilSeqContext, ModifiedBufferId, M_DEFAULT);
MbufCopy(ModifiedBufferId, UserHookDataPtr->MilImageDisp);
break;
}
return 0;
}
MIL_INT MFTYPE FrameEncodingEndFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr)
{
EncodingFrameEndHookDataStruct * UserHookDataPtr = (EncodingFrameEndHookDataStruct *)HookDataPtr;
if (HookType == M_FRAME_END)
{
MIL_ID CompressedBufferId;
void* CompressedDataPtr = M_NULL;
MIL_INT CompressedDataSize = 0;
UserHookDataPtr->EncodedImageCount++;
MseqGetHookInfo(HookId, M_MODIFIED_BUFFER + M_BUFFER_ID, &CompressedBufferId);
MbufInquire(CompressedBufferId, M_HOST_ADDRESS, &CompressedDataPtr);
MbufInquire(CompressedBufferId, M_SIZE_BYTE, &CompressedDataSize);
}
return 0;
}
MIL_INT MFTYPE FrameDecodingEndFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr)
{
DecodingFrameEndHookDataStruct * UserHookDataPtr = (DecodingFrameEndHookDataStruct *)HookDataPtr;
if (HookType == M_FRAME_END)
{
MIL_ID DecompressedBufferId;
UserHookDataPtr->DecodedImageCount++;
MseqGetHookInfo(HookId, M_MODIFIED_BUFFER + M_BUFFER_ID, &DecompressedBufferId);
MbufCopy(DecompressedBufferId, UserHookDataPtr->MilImageDisp);
}
return 0;
}
MIL_INT CheckMseqProcessError(MIL_ID MilApplication, MIL_ID MilCompressContext)
{
struct MSEQ_PARAM
{
MIL_TEXT_PTR ControlName;
MIL_INT ControlType;
MIL_INT OriginalValue;
MIL_INT EffectiveValue;
};
MIL_INT IsError = M_NO;
MIL_INT IsWarning = M_NO;
MIL_INT MilErrorCode = PrintMilErrorMessage(MilApplication);
if (MilErrorCode != M_NULL_ERROR)
{
MSEQ_PARAM MseqParamList[] = {
{ MIL_TEXT("M_STREAM_BIT_RATE_MODE"), M_STREAM_BIT_RATE_MODE, 0, 0 },
{ MIL_TEXT("M_STREAM_BIT_RATE"), M_STREAM_BIT_RATE, 0, 0 },
{ MIL_TEXT("M_STREAM_BIT_RATE_MAX"), M_STREAM_BIT_RATE_MAX, 0, 0 },
{ MIL_TEXT("M_STREAM_FRAME_RATE_MODE"), M_STREAM_FRAME_RATE_MODE, 0, 0 },
{ MIL_TEXT("M_STREAM_QUALITY"), M_STREAM_QUALITY, 0, 0 },
{ MIL_TEXT("M_STREAM_PROFILE"), M_STREAM_PROFILE, 0, 0 },
{ MIL_TEXT("M_STREAM_LEVEL"), M_STREAM_LEVEL, 0, 0 },
{ MIL_TEXT("M_STREAM_GROUP_OF_PICTURE_SIZE"), M_STREAM_GROUP_OF_PICTURE_SIZE, 0, 0 }};
MIL_INT MseqParamListSize = (sizeof(MseqParamList) / sizeof(MseqParamList[0]));
MIL_INT NumberOfModifiedParams = 0;
for (MIL_INT ParamIndex = 0; ParamIndex < MseqParamListSize; ParamIndex++)
{
MseqInquire(MilCompressContext,
M_CONTEXT,
MseqParamList[ParamIndex].ControlType,
&MseqParamList[ParamIndex].OriginalValue);
MseqInquire(MilCompressContext,
M_CONTEXT,
MseqParamList[ParamIndex].ControlType | M_EFFECTIVE_VALUE,
&MseqParamList[ParamIndex].EffectiveValue);
if (MseqParamList[ParamIndex].OriginalValue != MseqParamList[ParamIndex].EffectiveValue)
{
if (NumberOfModifiedParams == 0)
MosPrintf(MIL_TEXT("\nParameter(s) that have been internally modified:\n"));
MosPrintf(MIL_TEXT("- %s\n"), MseqParamList[ParamIndex].ControlName);
NumberOfModifiedParams++;
IsWarning = M_YES;
}
}
MosPrintf(MIL_TEXT("\n"));
if (!IsWarning)
IsError = M_YES;
}
return IsError;
}
MIL_INT PrintMilErrorMessage(MIL_ID MilApplication)
{
MIL_INT MilErrorCode;
MIL_TEXT_CHAR MilErrorMsg[M_ERROR_MESSAGE_SIZE];
MIL_INT MilErrorSubCode[3];
MIL_TEXT_CHAR MilErrorSubMsg[3][M_ERROR_MESSAGE_SIZE];
MilErrorCode = MappGetError(MilApplication, M_CURRENT + M_MESSAGE, MilErrorMsg);
if (MilErrorCode != M_NULL_ERROR)
{
MIL_INT subCount = 3;
MappGetError(MilApplication, M_CURRENT_SUB_NB, &subCount);
MilErrorSubCode[0] = MappGetError(MilApplication,
M_CURRENT_SUB_1 + M_MESSAGE,
MilErrorSubMsg[0]);
MilErrorSubCode[1] = MappGetError(MilApplication,
M_CURRENT_SUB_2 + M_MESSAGE,
MilErrorSubMsg[1]);
MilErrorSubCode[2] = MappGetError(MilApplication,
M_CURRENT_SUB_3 + M_MESSAGE,
MilErrorSubMsg[2]);
MosPrintf(MIL_TEXT("\nMseqProcess generated a warning or an error:\n"));
MosPrintf(MIL_TEXT(" %s\n"), MilErrorMsg);
for (int i = 0; i < subCount; i++)
{
if (MilErrorSubCode[i]) MosPrintf(MIL_TEXT(" %s\n"), MilErrorSubMsg[i]);
}
}
return MilErrorCode;
}