Click here to show toolbars of the Web Online Help System: show toolbars |
/*************************************************************************************/ /* * File name: MseqProcess.cpp * Location: See Matrox Example Launcher in the MIL Control Center * * * Synopsis: This program shows the use of the MseqProcess() and MseqFeed() functions * to perform real-time encoding of a sequence of captured images. * * The user's preprocessing and compression code is written in a hook * function that will be called by MdigProcess() for each frame grabbed * (see ProcessingFunction()). The queueing for encoding of the next * frame is also made in that hook function to allow fully parallel * execution of the capture and the encoding. * * Note: The average encoding time must be shorter than the grab time or * some frames will be missed. Missed frames are very frequent when * the encoding is done by software. Also, if the captured images * are not displayed and the frame count is not drawn or printed * in the hook function, the CPU usage is reduced significantly. * * When encoding a 1080p source it is recommended to have your * MIL Non-Paged Memory set to at least 64MB. * * Copyright (C) Matrox Electronic Systems Ltd., 1992-2016. * All Rights Reserved */ #include <mil.h> /* Number of images in the buffering grab queue. Generally, increasing this number gives better real-time grab. */ #define BUFFERING_SIZE_MAX 20 /* Target sequence file name and location. The temporary directory location can be reached with %temp% under Windows. */ #define SEQUENCE_FILE M_TEMP_DIR MIL_TEXT("SeqProcess.mp4") /* Remote target sequence file name and location if Distributed MIL is used. */ #define REMOTE_SEQUENCE_FILE MIL_TEXT("remote:///") SEQUENCE_FILE enum ProcessingHookOperation { DISPLAY, ENCODE, }; /* User's processing function prototype. */ MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr); /* User's processing function hook data structure. */ typedef struct { MIL_ID MilDigitizer; MIL_ID MilImageDisp; MIL_ID MilSeqContext; MIL_INT ProcessedImageCount; ProcessingHookOperation ProcessingOperation; } ProcessingHookDataStruct; /* Optional encoding end function prototype */ MIL_INT MFTYPE FrameEncodingEndFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr); /* Optional decoding end function prototype */ MIL_INT MFTYPE FrameDecodingEndFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr); /* Function to display the details about errors from MseqProcess(), if any */ MIL_INT CheckMseqProcessError(MIL_ID MilApplication, MIL_ID MilCompressContext); MIL_INT PrintMilErrorMessage(MIL_ID MilApplication); /* Optional encoding end function hook data structure. */ typedef struct { MIL_INT EncodedImageCount; MIL_ID DecompressContextID; } EncodingFrameEndHookDataStruct; /* Optional decoding end function hook data structure. */ typedef struct { MIL_INT DecodedImageCount; MIL_ID MilImageDisp; } DecodingFrameEndHookDataStruct; /* Main function. */ /* ---------------*/ 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; /* Allocate defaults. */ MappAllocDefault(M_DEFAULT, &MilApplication, &MilSystem, &MilDisplay, &MilDigitizer, &MilImageDisp); MsysInquire(MilSystem, M_OWNER_APPLICATION, &MilRemoteApplication); MilSystemLocation = MsysInquire(MilSystem, M_LOCATION, M_NULL); /* Check if the system is running under Windows. */ 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; } /* Inquire MIL licenses. */ 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; } /* Allocate the grab buffers and clear them. */ 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); /* Free buffers to leave space for possible temporary buffers. */ 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; } /* Initialize the User's processing function data structure only for Display. */ ProcessingUserHookData.MilDigitizer = MilDigitizer; ProcessingUserHookData.MilSeqContext = M_NULL; ProcessingUserHookData.MilImageDisp = MilImageDisp; ProcessingUserHookData.ProcessedImageCount = 0; ProcessingUserHookData.ProcessingOperation = DISPLAY; /* Start MdigProcess() to show the live camera output. */ MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize, M_START, M_DEFAULT, ProcessingFunction, &ProcessingUserHookData); /* Print a message. */ MosPrintf(MIL_TEXT("\nH.264 IMAGE SEQUENCE COMPRESSION.\n")); MosPrintf(MIL_TEXT("---------------------------------\n\n")); MosPrintf(MIL_TEXT("Press <Enter> to start compression.\r")); MosGetch(); /* Stop MdigProcess(). */ MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize, M_STOP, M_DEFAULT, ProcessingFunction, &ProcessingUserHookData); /* Inquire the rate at which the frames were grabbed using MdigProcess()*/ MdigInquire(MilDigitizer, M_PROCESS_FRAME_RATE, &EncodingDesiredFrameRate); MosPrintf(MIL_TEXT("Grabbing frames at %.2f frames/sec.\n"), EncodingDesiredFrameRate); /* Creates a context for the H.264 compression engine. Compression will be done using hardware or software depending on the system hardware configuration. */ MseqAlloc(MilSystem, M_DEFAULT, M_SEQ_COMPRESS, M_DEFAULT, M_DEFAULT, &MilCompressContext); /* Specify the destination of the compressed file and the target container type. The last argument specifies to generate an MP4 file. */ MseqDefine(MilCompressContext, M_SEQ_OUTPUT(0) + M_SEQ_DEST(0), M_FILE, (MilSystemLocation != M_REMOTE ? SEQUENCE_FILE : REMOTE_SEQUENCE_FILE), M_FILE_FORMAT_MP4); /* Set the compression context's settings. */ /* Sets the compression context's settings to compress frames at any resolution under 1920 x 1080. Any resolution higher than that will generate a warning that can be disabled using MseqControl with M_SETTING_AUTO_ADJUSTMENT. See documentation for more details. */ MseqControl(MilCompressContext, M_CONTEXT, M_STREAM_BIT_RATE_MODE, M_VARIABLE); // M_VARIABLE or M_CONSTANT MseqControl(MilCompressContext, M_CONTEXT, M_STREAM_BIT_RATE, 5000); // 5 Mbps bit rate MseqControl(MilCompressContext, M_CONTEXT, M_STREAM_BIT_RATE_MAX, 5000); // 5 Mbps bit rate if (EncodingDesiredFrameRate != 0) MseqControl(MilCompressContext, M_CONTEXT, M_STREAM_FRAME_RATE, EncodingDesiredFrameRate); MseqControl(MilCompressContext, M_CONTEXT, M_STREAM_FRAME_RATE_MODE, M_VARIABLE); // Attempts to update the file header with the encoding frame rate // if lower than the specified frame rate. MseqControl(MilCompressContext, M_CONTEXT, M_STREAM_QUALITY, 100); // 1=best speed, 100=best quality MseqControl(MilCompressContext, M_CONTEXT, M_STREAM_PROFILE, M_PROFILE_HIGH); // M_PROFILE_BASELINE, M_PROFILE_MAIN, M_PROFILE_HIGH MseqControl(MilCompressContext, M_CONTEXT, M_STREAM_LEVEL, M_LEVEL_4_2); // M_LEVEL_1, M_LEVEL_1B, M_LEVEL_1_1, M_LEVEL_1_2, M_LEVEL_1_3, // M_LEVEL_2, M_LEVEL_2_1, M_LEVEL_2_2, // M_LEVEL_3, M_LEVEL_3_1, M_LEVEL_3_2, // M_LEVEL_4, M_LEVEL_4_1, M_LEVEL_4_2, // M_LEVEL_5, M_LEVEL_5_1 MseqControl(MilCompressContext, M_CONTEXT, M_STREAM_GROUP_OF_PICTURE_SIZE, 30); // Interval between I-Frame /* Initialize the optional encoding end function data structure. */ EncodingFrameEndUserHookData.EncodedImageCount = 0; /* Register the encoding end function to the sequence context. */ MseqHookFunction(MilCompressContext, M_FRAME_END, FrameEncodingEndFunction, &EncodingFrameEndUserHookData); /* Provide a sample image to initialize the encoding engine accordingly. */ MseqControl(MilCompressContext, M_CONTEXT, M_BUFFER_SAMPLE, MilGrabBufferList[0]); /* Disable error prints because MseqProcess() might not support the current input source. */ MappControl(M_ERROR, M_PRINT_DISABLE); /* Start the encoding process, waits for buffer to be fed for encoding. */ MseqProcess(MilCompressContext, M_START, M_ASYNCHRONOUS); /* Checks if an error has been logged by MseqProcess(). If so, stop the example. */ if (CheckMseqProcessError(MilApplication, MilCompressContext)) { /* An error happened during MseqProcess() and we need to free the allocated resources. */ 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; } /* MseqProcess() is running without error, so re-enable the error print. */ MappControl(M_ERROR, M_PRINT_ENABLE); /* Display the type of compression used. */ 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 // M_SOFTWARE + M_QSV MosPrintf(MIL_TEXT("Software implementation.\n")); /* Set the sequence context id in the user hook data structure to start feeding buffers for encoding in ProcessingFunction. */ ProcessingUserHookData.MilSeqContext = MilCompressContext; ProcessingUserHookData.ProcessedImageCount = 0; ProcessingUserHookData.ProcessingOperation = ENCODE; MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize, M_START, M_DEFAULT, ProcessingFunction, &ProcessingUserHookData); /* NOTE: Now the main() is free to perform other tasks while the compression is executing. */ /* --------------------------------------------------------------------------------------- */ /* Print a message and wait for a key press after a minimum number of frames. */ MosPrintf(MIL_TEXT("Press <Enter> to stop.\n\n")); MosGetch(); /* Stop the processing. */ MdigProcess(MilDigitizer, MilGrabBufferList, MilGrabBufferListSize, M_STOP + M_WAIT, M_DEFAULT, ProcessingFunction, &ProcessingUserHookData); /* Stop the encoding process */ MseqProcess(MilCompressContext, M_STOP, M_WAIT); /* Print statistics. */ 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")); /* Free the grab buffers and sequence context. */ while (MilGrabBufferListSize > 0) { MbufFree(MilGrabBufferList[--MilGrabBufferListSize]); MilGrabBufferList[MilGrabBufferListSize] = M_NULL; } if (SeqProcessFilePath) { delete[] SeqProcessFilePath; SeqProcessFilePath = M_NULL; } MseqFree(MilCompressContext); /* Wait for a key to start the replay. */ MosPrintf(MIL_TEXT("Press <Enter> to replay encoded sequence.\n")); MosGetch(); MseqAlloc(MilSystem, M_DEFAULT, M_SEQ_DECOMPRESS, M_DEFAULT, M_DEFAULT, &MilDecompressContext); /* Specify the destination of the compressed file and the target container type. The last argument specifies to generate an MP4 file. */ 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); /* Initialize the optional decoding end function data structure. */ DecodingFrameEndUserHookData.DecodedImageCount = 0; DecodingFrameEndUserHookData.MilImageDisp = MilImageDisp; /* Register the decoding end function to the sequence context. */ MseqHookFunction(MilDecompressContext, M_FRAME_END, FrameDecodingEndFunction, &DecodingFrameEndUserHookData); /* Start the decoding process, waits for buffer to be fed for encoding. */ MseqProcess(MilDecompressContext, M_START, M_ASYNCHRONOUS); /* Print a message and wait for a key press after a minimum number of frames. */ MosPrintf(MIL_TEXT("Press <Enter> to stop.\n\n")); MosGetch(); /* Stop the play back. */ MseqProcess(MilDecompressContext, M_STOP, M_NULL); MseqFree(MilDecompressContext); /* Wait for a key to end. */ MosPrintf(MIL_TEXT("Press <Enter> to end.\n")); MosGetch(); /* Release defaults. */ MappFreeDefault(MilApplication, MilSystem, MilDisplay, MilDigitizer, MilImageDisp); return 0; } /* Local defines. */ #define STRING_LENGTH_MAX 20 #define STRING_POS_X 20 #define STRING_POS_Y 20 /* User's processing function called every time a grab buffer is modified. */ /* ------------------------------------------------------------------------*/ 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'), }; /* Retrieve the MIL_ID of the grabbed buffer. */ MdigGetHookInfo(HookId, M_MODIFIED_BUFFER + M_BUFFER_ID, &ModifiedBufferId); switch (UserHookDataPtr->ProcessingOperation) { case DISPLAY: /* Update the display with the last captured image. */ MbufCopy(ModifiedBufferId, UserHookDataPtr->MilImageDisp); break; case ENCODE: /* Increase the compressed images count. */ UserHookDataPtr->ProcessedImageCount++; /* Print and draw the frame count (comment this block to reduce CPU usage). */ 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); /* Enqueue the grabbed buffer for parallel encoding. */ MseqFeed(UserHookDataPtr->MilSeqContext, ModifiedBufferId, M_DEFAULT); /* Update the display with the last captured image. */ MbufCopy(ModifiedBufferId, UserHookDataPtr->MilImageDisp); break; } return 0; } /* Optional encoding end function called every time a buffer is finished being compressed. */ /* ----------------------------------------------------------------------------------------*/ MIL_INT MFTYPE FrameEncodingEndFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr) { EncodingFrameEndHookDataStruct * UserHookDataPtr = (EncodingFrameEndHookDataStruct *)HookDataPtr; /* Frame end hook post processing. */ if (HookType == M_FRAME_END) { MIL_ID CompressedBufferId; void* CompressedDataPtr = M_NULL; MIL_INT CompressedDataSize = 0; /* Increment a encoded frame counter */ UserHookDataPtr->EncodedImageCount++; /* Retrieve the MIL_ID of the encoded buffer. */ MseqGetHookInfo(HookId, M_MODIFIED_BUFFER + M_BUFFER_ID, &CompressedBufferId); /* Retrieves the address of the encoded data. */ MbufInquire(CompressedBufferId, M_HOST_ADDRESS, &CompressedDataPtr); /* Retrieves the size in bytes of the encoded data. */ MbufInquire(CompressedBufferId, M_SIZE_BYTE, &CompressedDataSize); /* -----------------------------------------------------------------------------------------------*/ /* Here you can do any action with the encoded data, such as send the buffer through a network */ /* stream. If the processing done on the compressed data is long, it is recommended to copy the */ /* buffer and to process it in a separate thread to avoid blocking the compression's flow. */ /* -----------------------------------------------------------------------------------------------*/ } return 0; } /* Optional decoding end function called every time a buffer is finished being decompressed. */ /* ----------------------------------------------------------------------------------------*/ MIL_INT MFTYPE FrameDecodingEndFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr) { DecodingFrameEndHookDataStruct * UserHookDataPtr = (DecodingFrameEndHookDataStruct *)HookDataPtr; /* Frame end hook post processing. */ if (HookType == M_FRAME_END) { MIL_ID DecompressedBufferId; /* Increment a encoded frame counter */ UserHookDataPtr->DecodedImageCount++; /* Retrieve the MIL_ID of the encoded buffer. */ MseqGetHookInfo(HookId, M_MODIFIED_BUFFER + M_BUFFER_ID, &DecompressedBufferId); /* -----------------------------------------------------------------------------------------------*/ /* Here you can do any action with the decoded buffer. */ /* -----------------------------------------------------------------------------------------------*/ MbufCopy(DecompressedBufferId, UserHookDataPtr->MilImageDisp); } return 0; } /* Checks if MseqProcess generated an error or a warning. */ /* This function prints out the MIL error message, if any. */ /* If a sequence context parameter has been modified, it means that only a warning has been generated. */ /* If it is a warning, it displays the control that has been modified. */ /* If it is an error, it return M_YES to indicate that the example needs to be stopped. */ /* ----------------------------------------------------------------------------------------------------*/ 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); /* MseqProcess generated an error, check in details if it is a warning or an error*/ 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; /* Loop though the param list to find which one has been internally modified. */ for (MIL_INT ParamIndex = 0; ParamIndex < MseqParamListSize; ParamIndex++) { /* Query the original control values. */ MseqInquire(MilCompressContext, M_CONTEXT, MseqParamList[ParamIndex].ControlType, &MseqParamList[ParamIndex].OriginalValue); /* Query the effective control values. */ MseqInquire(MilCompressContext, M_CONTEXT, MseqParamList[ParamIndex].ControlType | M_EFFECTIVE_VALUE, &MseqParamList[ParamIndex].EffectiveValue); /* If the original value is different than the effective value, the error received is only a warning and processing can continue. */ if (MseqParamList[ParamIndex].OriginalValue != MseqParamList[ParamIndex].EffectiveValue) { if (NumberOfModifiedParams == 0) MosPrintf(MIL_TEXT("\nParameter(s) that have been internally modified:\n")); /* Prints the Control type internally modified. */ MosPrintf(MIL_TEXT("- %s\n"), MseqParamList[ParamIndex].ControlName); NumberOfModifiedParams++; IsWarning = M_YES; } } MosPrintf(MIL_TEXT("\n")); /* If the error logged is not a warning, you cannot encode the current input source. The example needs to be stopped. */ if (!IsWarning) IsError = M_YES; } return IsError; } /* Print the current error code in the console */ 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) { /* Collects Mil error messages and sub-messages */ 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; }