This chapter describes the ML parameter syntax and semantics. These parameters define variables including control values (such as the frame rate or image width) and location of data (such as a single video field).
This chapter contains the following sections:
The fundamental building block of ML is the param/value pair that makes up an MLpv message, as shown here:
typedef struct { MLint64 param; MLvalue value; MLint32 length; MLint32 maxLength; } MLpv; |
The param is a unique numeric identifier for each parameter and the value is a union of several possible types. For example:
typedef union { MLbyte byte; /* 8-bit signed byte values */ MLint32 int32; /* 32-bit signed integer values */ MLint64 int64; /* 64-bit signed integer values */ MLbyte* pByte; /* pointer to an array of bytes */ MLreal32* real32; /* 32-bit floating point value */ MLreal64* real64; /* 64-bit floating point value */ MLint32* pInt32; /* pointer to an array of 32-bit signed integer values */ MLint64* pInt64; /* pointer to an array of 64-bit signed integer values */ MLreal32* pReal32; /* pointer to an array of 32-bit floating point values */ MLreal64* pReal64; /* pointer to an array of 64-bit floating point values */ struct_MLpv*pPv; /* pointer to a message of param/value pairs*/ struct_MLpv** ppPv;/* pointer to an array of messages */ }MLvalue; |
In ML, applications communicate with devices using messages. Each message is a simple array of param/value pairs. An MLpv message ends with the ML_END parameter to indicate completion.
For example, the following is a message that sets image width to 1920 and image height to 1080:
MLpv controls[3]; controls[0].param = ML_IMAGE_WIDTH_INT32; controls[0].value.int32 = 1920; controls[1].param = ML_IMAGE_HEIGHT_INT32; controls[1].value.int32 = 1080; controls[2].param = ML_END; |
This section shows you how to set and get scalar values.
To set the values of scalar parameters, you must enter the param and value fields of each MLpv and send the result to a device. If the value is valid, the returned length will be 1. If the value is invalid, or if the parameter is not recognized by the device, an error status will be returned and length will be set to -1.
![]() | Note: Do not set the length or maxLength fields because they are ignored when setting scalars. However, on return (mlReceiveMessage), a length parameter that equals -1 indicates that this parameter was in error. |
For example, to set video timing:
MLpv message[2]; message[0].param = ML_VIDEO_TIMING_INT32; message[0].value.int32 = ML_TIMING_525; message[1].param = ML_END; if( mlSetControls( someOpenVideoPath, message) ) fprintf(stderr, "Error, unable to set timing\n"); |
To get scalar values, you again construct a MLpv list, but you do not need to set the value field. As the device processes the MLpv list, it fills in the value and length fields. If the value is valid, the returned length is 1. If the value is invalid, or the parameter is not recognized by the device, an error status will be returned and length is set to -1.
For example, to get video timing:
MLpv message[2]; message[0].param = ML_VIDEO_TIMING_INT32; message[1].param = ML_END; mlGetControls( someOpenVideoPath, message); if( message[0].length == 1 ) printf("Timing is %d\n", message[0].value.int32); else fprintf(stderr, "Unable to determine timing\n"); |
An array in ML is much like an array in C:
value of the MLpv is a pointer to the first element of the array
length is the number of valid elements in the array
maxLength is the total length of the array
Each element increases the length of the array by 1, so an array of four 32-bit integers would require a maxLength of four.
To set the value of an array parameter, fill out the param , value, length, and maxLength fields. If the values are valid, the returned length will be unaltered. If the values are invalid or if the parameter is not recognized at all by the device, an error status will be returned and length will be set to -1.
For example, use ML_AUDIO_GAINS_REAL64_ARRAY to set the gain on a 4-channel audio path:
MLreal64 data[] = { -12.0, 1.0, 1.0, 12.0 }; MLpv message[2]; message[0].param = ML_AUDIO_GAINS_REAL64_ARRAY; message[0].value.pReal64 = data; message[0].length = sizeof(data) / sizeof(MLreal64) message[1].param = ML_END; mlSetControls( someOpenPath, message ); |
![]() | Note: Do not set the maxLength field because it is ignored when setting an array parameter. |
In the preceding example, you are free to modify the data array at any time before calling mlSetControls. You regain that right as soon as mlSetControls returns.
If you have a multithreaded application, your application must ensure that the data array is not accessed by some other thread while the SetControls call is in progress.
To get the size of an array parameter, set maxLength to 0. The device will fill in maxLength to indicate the minimal array size to hold that value. If the parameter is not recognized by the device, an error status will be returned, maxLength will be set to 0, and length will be set to -1.
MLpv message[2]; message[0].param = ML_PATH_TYPE_REAL64_ARRAY; message[0].length = 0; message[0].maxLength = 0; message[1].param = ML_END; mlGetControls( someOpenPath, message ); printf("Size of real array is %d\n", message[0].maxLength); |
To get the value of an array parameter, create an array with maxLength entries to hold the result, and set length to 0. The device will fill in no more than maxLength array elements and set length to indicate the number of valid entries. If the values are invalid or if the parameter is not recognized at all by the device, an error status will be returned and length will be set to -1.
MLint32 data[10]; MLpv message[2]; message[0].param = ML_PATH_TYPE_INT32_ARRAY; message[0].value.pInt32 = data; message[0].length = 0; message[0].maxLength = 10; message[1].param = ML_END; mlGetControls( someOpenPath, message ); if( message[0].length > 0 ) { printf("Received %d array entries\n", message[0].length); printf("The first entry is %d\n", data[0]); } |
![]() | Note: Your application controls memory allocation. If you
want to get the whole array, but do not know the maximum size, you must
do the following:
|
The distinction between array values and pointer values in ML is subtle, but important.
Array values are copied when they are passed to or received from a device. Thus, your application owns the array memory and is nearly always free to modify or free it.
A pointer parameter is a special type of array parameter that is used to send and receive data buffers (as arrays of bytes.) Pointer values are not copied. Instead, only the location of the data is passed to the device. The application sends a buffer by calling mlSendBuffer. mlSendBuffer places the controls and buffer pointer in the data payload area and inserts a header on the send queue for the device.
This is much more efficient, but it imposes a restriction: after a pointer value is given to a device, that memory cannot be touched until the device has finished processing it.
![]() | Note: For efficient processing, all buffers must be pinned in memory. |
For example, the following code fragment shows how a pointer parameter might be initialized to send an image to a video input path:
MLpv message[2]; message[0].param = ML_IMAGE_BUFFER_POINTER; message[0].value.pByte = someBuffer; message[0].maxLength = sizeof(someBuffer); message[1].param = ML_END; if( mlSendBuffers( someOpenPath, message ) ) fprintf(stderr, "Error sending buffers\n"); |
The above mlSendBuffers call places the message on a queue to be processed by the device, and then returns. It does not wait for the device to finish with the buffer. Thus, even after the call to mlSendBuffers, the device still owns the image buffer. Your application must not touch that memory until it is notified that processing is complete.
When you send a buffer to be filled, the device uses maxLength to determine how much it may write. It returns length set to indicate the amount of the buffer it actually used.
When you send a buffer for output, the device will interpret the length as the maximum number of bytes of valid data in the buffer. In this case, maxLength is ignored.