The MFStrGet() and MFDataGet() methods provide powerful and flexible ways to access metadata and side data embedded in multimedia frames within our SDK. This article shows how to use these methods to extract various types of frame-level information, including CRC checksums, subtitle tracks, SCTE-35 triggers, and text overlay metadata.
Method Overview
MFStrGet(key, out string value)
Retrieves a string value associated with a key from the frame's side data.
MFDataGet(key, out int size, out long pointer)
Retrieves binary data associated with a key, along with its size and a pointer to the memory location.
Both methods operate on objects implementing the IMFFrame interface.
Frame Checksum Calculation
The "__crc32_" key provides a CRC32 checksum of the frame's raw data:
((IMFFrame)pFrame).MFDataGet("__crc32_", out int size, out long pointer);Purpose: Identify frozen frames or detect visual repetition.
Behavior: The CRC32 is calculated on demand, requiring a memory scan.
Performance: For a small number of channels, this operation is fast enough to be used in real-time comparisons.
Note: Identical frames will yield the same CRC32, while even a 1-pixel change will alter the checksum.
Extracting Closed Caption Subtitles
These keys expose embedded subtitle data in the frame:
((IMFFrame)pFrame).MFDataGet("C608", out int size608, out long ptr608);
if (size608 > 0 && ptr608 != 0)
{
IntPtr src = new IntPtr(ptr608);
byte[] bytes608 = new byte[size608];
Marshal.Copy(src, bytes608, 0, size608);
string hex608 = BitConverter.ToString(bytes608).Replace("-", "");
}C608: Line 21 closed captions (NTSC).
C708: DTV closed captions.
Use this to extract subtitle data directly from the stream for further processing or display.
Handling SCTE-35 Signaling Data
These keys allow handling of SCTE-35 messages used in digital broadcast signaling (e.g., ad insert triggers).
Retrieve the parsed SCTE-35 message as an XML string::
((IMFFrame)pFrame).MFStrGet("SCTE-35", out string strTrigger);Retrieve raw SCTE-35 (Hex) binary packet:
((IMFFrame)pFrame).MFDataGet("SCTE-35.PKT", out int nSize, out long lPointer);
if (lPointer != 0 && nSize > 0)
{
byte[] data = new byte[nSize];
Marshal.Copy(new IntPtr(lPointer), data, 0, nSize);
string hex = BitConverter.ToString(data).Replace("-", "");
}SCTE-35: Parsed SCTE-35 command as a human-readable xml.
SCTE-35.PKT: Raw message in binary form.
This is particularly useful for compliance, diagnostics, and ad-insertion workflows.
Retrieving Text Overlay Geometry
After calling MFPrint(), you can immediately retrieve the calculated position and dimensions of the rendered text using MFStrGet():
// Apply text overlay to the frame
mFrame.MFPrint(strTextContent, dblTextSizelocked, ref rcOverlay, eMFTextFlags.eMFT_WordBreaks, strTextConfig);
// Retrieve calculated text overlay dimensions
mFrame.MFStrGet("MFPrint.X", out string MFPrint_X);
mFrame.MFStrGet("MFPrint.Y", out string MFPrint_Y);
mFrame.MFStrGet("MFPrint.Width", out string MFPrint_Width);
mFrame.MFStrGet("MFPrint.Height", out string MFPrint_Height);
Console.WriteLine($"X:{MFPrint_X} Y:{MFPrint_Y} W:{MFPrint_Width} H:{MFPrint_Height}");
MFPrint.X, MFPrint.Y: Position of the text block within the frame.
MFPrint.Width, MFPrint.Height: Dimensions of the rendered text area.
All values are returned as strings (e.g., "100", "35").
This mechanism enables precise inspection of the text layout right after rendering, which is helpful for dynamic layouting, debugging, or subsequent processing.
V-Chip Data
If a video source contains V-Chip data, it's possible to obtain it via .MFStrGet() method. It can be done the following way:
(pMFrame as IMFFrame).MFStrGet("XDS", out string XDSData);Important note! To ensure that XDS data is present in the frames, the frames have to be processed by MCCDisplay (CC plugin must be added).
If you need just to obtain the XDS data but its overlaying it is not required, you can disable CC rendering by setting show_subtitles prop as false:
m_objMCCDisplay.PropsSet("show_subtitles", "false");Note: V-Chip data is not necessarily present in the first frames of the video source. Therefore, if you need this data, you should check for V-Chip information on every frame.
Other String Frame Metadata
Below is a table of the remaining frame string metadata that can be obtained using the MFStrGet() method:
| Metadata Name | Description |
| SRMT_START_TIME |
Contains actual, unmodified frame position in a video. Useful when playing videos with a changed play rate. pFrame.MFStrGet("SRMT_START_TIME", out String SrmtStr);
Double.TryParse(SrmtStr, out Double RealFramePositon);
RealFramePositon*= 1e-7; // Frame position in seconds
|
| subtitle.stream_info | Contains information about all the subtitle tracks in a video. |
| SCTE-35 | Contains information about SCTE-35 trigger in the current frame. |
| SCTE-104 | Contains information about SCTE-104 trigger in the current frame. |
| unix_utc | Specifies the time of the moment when we put the frame into the MDelay. |
Other Raw Frame Metadata
Below is a table of the remaining frame raw metadata that can be obtained using the MFDataGet() method:
| Metadata Name | Description |
C608 |
Provides a byte pair of CC608. To decode the pair into 2 chars, you can use the following approach: (pMFrame as IMFFrame).MFDataGet("C608", out Int32 dataSize, out Int64 dataPointer);
if (dataSize != 0)
{
byte[] CC608_Frame_Data = new byte[dataSize];
IntPtr Ptr = new IntPtr(dataPointer);
Marshal.Copy(Ptr, CC608_Frame_Data, 0, dataSize);
String DecodedChars = Encoding.ASCII.GetString(CC608_Frame_Data);
}
|
C708 |
Provides a byte packet of CC708: (pMFrame as IMFFrame).MFDataGet("C708", out Int32 dataSize, out Int64 dataPointer);
if (dataSize != 0)
{
byte[] CC708_Frame_Data = new byte[dataSize];
IntPtr Ptr = new IntPtr(dataPointer);
Marshal.Copy(Ptr, CC708_Frame_Data, 0, dataSize);
}
|
ATSC |
Provides a byte packet of ATSC: (pMFrame as IMFFrame).MFDataGet("ATSC", out Int32 dataSize, out Int64 dataPointer);
if (dataSize != 0)
{
byte[] ATSC_Frame_Data = new byte[dataSize];
IntPtr Ptr = new IntPtr(dataPointer);
Marshal.Copy(Ptr, ATSC_Frame_Data, 0, dataSize);
}
|
GA94 |
Provides a byte packet of GA94: (pMFrame as IMFFrame).MFDataGet("GA94", out Int32 dataSize, out Int64 dataPointer);
if (dataSize != 0)
{
byte[] GA94_Frame_Data = new byte[dataSize];
IntPtr Ptr = new IntPtr(dataPointer);
Marshal.Copy(Ptr, GA94_Frame_Data, 0, dataSize);
}
|
hwtm_abs |
An absolute hardware timestamp provided by the Blackmagic Design (BMD) equipment. It is an Int64 value where each unit represents 100 nanoseconds. This timestamp marks the precise moment a frame is sent to the SDI output by the BMD renderer. This metadata is essential for achieving high-precision synchronization between multiple independent BMD sources (e.g., multiple MFLive or MLive instances) at the application level. By comparing the hwtm_abs values of frames from different sources, an application can identify which frames were generated by the hardware at virtually the same time and pair them together. (Frame_Live_1 as IMFFrame).MFDataGet("hwtm_abs", out _, out Int64 HWTime_FrameLive_1);
(Frame_Live_2 as IMFFrame).MFDataGet("hwtm_abs", out _, out Int64 HWTime_FrameLive_2);
Note: This synchronization method works exclusively for video processed by BMD devices. More information about using this prop can be found in this article. |