MPlatform and MFormats allow applications to attach custom ANC packet descriptions to video frames. A compatible renderer can insert these packets into its hardware output, and a capture device can expose received packets on incoming frames.
Applications write and read these descriptions through the MFStrSet and MFStrGet methods of the IMFFrame interface.
ANC packet string format
Use an ANC.Line.N string to associate packets with a particular video line:
myMFFrame.MFStrSet("ANC.Line.2", "<packet did='0x58' sdid='0x77'>01A0F203040B506C</packet>");The number in the string ID identifies the requested line:
ANC.Line.2refers to line 2.ANC.Line.8refers to line 8.
Available ANC lines depend on the video format, device and driver. Check that the selected line is supported by your output and capture configuration.
The packet description contains the following attributes and data:
| Element | Meaning |
|---|---|
did |
Data Identifier. |
sdid |
Secondary Data Identifier used by Type 2 packets. Specify it explicitly. If omitted, the SDK uses 0, which is reserved by SMPTE ST 291-1. |
dbn |
Data Block Number used by Type 1 packets. It can identify a continuation of a larger message. |
| Packet text | Payload represented as hexadecimal byte pairs. For example, 01A0F203040B506C represents eight bytes. |
Use an even number of hexadecimal digits. An unmatched final digit is discarded by the SDK’s HEX conversion.
MFStrSet stores the supplied string; it does not validate the packet or confirm its transmission. Setting the same string ID again replaces its previous value. To place multiple packets on one line, include all their descriptions in the same string.
Writing ANC packets
For MPlatform, modify the outgoing frame in the OnFrameSafe handler of the MRenderer object. Use synchronous callbacks so the changes are applied before the renderer processes the frame:
m_objRenderer.PropsSet("on_frame.sync", "true");With asynchronous delivery, the callback receives a separate frame object, so changing it does not provide the same guarantee of modifying the frame being output.
For MFormats, call MFStrSet on each outgoing frame before passing it to MFRenderer:
myMFFrame.MFStrSet("ANC.Line.2", "<packet did='0x58' sdid='0x77'>01A0F203040B506C</packet>");
m_objRenderer.ReceiverFramePut(myMFFrame, -1, "");Type 1: a short message on line 8
For custom Type 1 applications, use a DID from the User Application range 0xC0–0xCF:
myMFFrame.MFStrSet("ANC.Line.8", "<packet did='0xCF'>010203040506070809</packet>");Type 1 messages longer than 255 payload bytes are divided into packets of up to 255 bytes. Unless a starting dbn is supplied, numbering starts at 1.
This fragmentation does not automatically move overflowing data to another video line. The complete message, including packet headers and checksums, must fit in the available ANC space on the selected line. Otherwise, data can be lost.
There is no universal per-line payload size that applies to every video format and device.
Type 1: continuing a message on another line
To distribute a larger message across lines, split the payload yourself and specify the starting DBN for each continuation.
The following example creates a 1200-byte message. The first 1020 bytes produce four packets with DBN values 1–4; the remaining bytes start on the next line with DBN 5:
Byte[] UserData = new Byte[1200];
for (Int32 Index = 0; Index < UserData.Length; Index++)
{
UserData[Index] = (Byte)(Index % 256);
}
String FirstLineData = BitConverter.ToString(UserData, 0, 1020).Replace("-", "");
String SecondLineData = BitConverter.ToString(UserData, 1020, UserData.Length - 1020).Replace("-", "");
myMFFrame.MFStrSet("ANC.Line.2", "<packet did='0xCF'>" + FirstLineData + "</packet>");
myMFFrame.MFStrSet("ANC.Line.3", "<packet did='0xCF' dbn='5'>" + SecondLineData + "</packet>");Use these lines and payload sizes only where supported by the selected output mode. The receiving application is responsible for reconstructing the message from its packets and DBN values.
Type 2: one packet on line 2
For custom Type 2 applications, use a DID from the User Application range 0x50–0x5F and specify the SDID:
myMFFrame.MFStrSet("ANC.Line.2", "<packet did='0x58' sdid='0x77'>010203040506070809</packet>");A Type 2 packet carries at most 255 payload bytes in this interface. Larger payloads are truncated to 255 bytes rather than automatically fragmented. Validate their size before submitting them.
The DID ranges above identify User Application allocations, not the complete ranges of all Type 1 and Type 2 packets. See SMPTE ST 291-1 for packet fields and identifier assignments.
Type 2: multiple packets on line 8
Concatenate the packet descriptions in one MFStrSet call:
myMFFrame.MFStrSet("ANC.Line.8", "<packet did='0x58' sdid='0x77'>010203040506070809</packet><packet did='0x55' sdid='0x17'>FF010203040506070809</packet>");All packets must fit in the available space on that line.
Reading ANC packets
For MPlatform, read the incoming frame’s strings inside the MLive.OnFrameSafe handler.
For MFormats, read them from frames retrieved through MFLive.SourceFrameGet.
The following MPlatform callback uses MPLATFORMLib and System.Runtime.InteropServices:
void m_objMLive_OnFrameSafe(String ChannelId, Object FrameObject)
{
try
{
// Read ANC data from line 2.
((IMFFrame)FrameObject).MFStrGet("ANC.Line.2", out String AncData);
if (!String.IsNullOrEmpty(AncData))
{
Console.WriteLine(AncData);
}
}
finally
{
if (FrameObject != null)
{
Marshal.ReleaseComObject(FrameObject);
}
}
}A missing line can return a null or empty string.
Received descriptions may contain several packets and may use normalized attribute names, hexadecimal formatting or an enclosing line element. Parse their fields and payloads instead of comparing the complete XML string with the original input.
Configuring ANC packet processing
Blackmagic capture
Custom ANC packet extraction is disabled by default. Enable it before selecting and starting the capture device.
For MFormats:
m_objLive.PropsSet("vanc.capture_anc", "true");The corresponding Blackmagic device registry setting is:
[HKEY_CURRENT_USER\SOFTWARE\Medialooks\MFormats\MFLive\BMD]
vanc.capture_anc = trueFor MPlatform MLive:
m_objMLive.PropsSet("object::vanc.capture_anc", "true");The vanc.capture_anc setting enables extraction into ANC.Line.N strings. The separate vanc.capture option controls raw VANC capture; it should not be treated as an interchangeable name for ANC packet extraction.
Blackmagic output
Custom ANC packet output is enabled by default. It can be set explicitly on the renderer:
m_objRenderer.PropsSet("output.anc_packets", "true");The registry locations are:
MPlatform:
[HKEY_CURRENT_USER\SOFTWARE\Medialooks\MPlatform\MRenderer]
output.anc_packets = trueMFormats:
[HKEY_CURRENT_USER\SOFTWARE\Medialooks\MFormats\MFRenderer\BMD]
output.anc_packets = trueOutput bit depth and older devices
Some older Blackmagic devices require 10-bit output for ANC insertion.
The legacy Blackmagic renderer backend supports the following setting:
MPlatform:
[HKEY_CURRENT_USER\SOFTWARE\Medialooks\MPlatform\MRenderer]
output.10bit = trueMFormats:
[HKEY_CURRENT_USER\SOFTWARE\Medialooks\MFormats\MFRenderer\BMD]
output.10bit = trueThis is not a universal switch for every Blackmagic backend. The newer backend selects an appropriate output pixel format automatically, including 10-bit output for relevant older models. Check the active backend, device model and output format when troubleshooting bit-depth requirements.
Hardware output scope and limitations
The hardware examples in this article describe Blackmagic SDI output and capture. Support on other devices depends on their SDK backend and hardware capabilities.
The SDI workflow does not limit the frame metadata API to SDI sources. ANC data can also be available from supported file inputs, including MXF files containing a SMPTE ST 436 ANC stream.
A successful
MFStrSetcall confirms only that the string was stored. Verify actual output by capturing the signal and inspecting the received packets.Packet size, line availability and existing ANC traffic determine whether the requested data can be transmitted without loss.
Refer to SMPTE ST 291-1 and the device documentation when choosing identifiers, lines and payload sizes.
Decoding OP-47 pages and text
OP-47 transports Teletext through ANC packets. Alongside the original ANC.Line.N descriptions, the SDK can expose discovered pages and the selected page’s Unicode text.
Page contents accumulate over successive frames. Process enough frames to receive a page’s transmission cycle rather than expecting complete text immediately. Decoding retains the original ANC packet descriptions.
Supported input paths include:
Files containing a SMPTE ST 436 ANC stream, read through
MFReaderor the reader-backedMFilepath.Blackmagic capture through
MFLiveorMLivewithbmd.new_api=true.
The decoder handles OP-47 packets with DID 0x43 and SDID 0x02 or 0x03.
These fields apply to OP-47 ANC data. For DVB Teletext subtitle streams, see Displaying DVB subtitles/teletext from transport stream.
Frame string fields
Retrieve the following values using IMFFrame.MFStrGet. These are decoder outputs, not settings to write on the source.
Fields may be absent before decoding has produced any page state. Empty text or language is also a valid result.
| String ID | Format | Description |
|---|---|---|
OP47_PAGE_LIST |
Comma-separated hexadecimal page numbers | Discovered pages for the selected ANC source, sorted numerically, such as 801,802,888. Clearing the catalog produces an empty list. |
OP47_PAGE_NUMBER |
Hexadecimal page number | Current selection or explicit request. A value such as 888 can appear before that page arrives. Empty when nothing is selected. |
OP47_TEXT |
Unicode text with LF row separators | Visible page text without its header. Leading spaces are retained; trailing spaces and blank rows are removed. Concealed characters and mosaics are omitted, with subtitle boxes and double-height visibility taken into account. |
OP47_LANGUAGE |
Two- or three-letter ISO 639 code | Language explicitly associated with the page by the selected ANC stream’s metadata. Empty when no unambiguous declaration is available. |
OP47_CHARSET_CANDIDATES |
Language names separated by comma and space | Languages associated with the page’s character set, for example Swedish, Finnish, Hungarian. This does not establish the actual page language. |
OP47_ANC_STREAM |
Decimal stream index | Absolute reader stream index matching info::data.N::idx. It is neither a PID nor the data-track ordinal N. Empty for capture or cleared output. |
OP47_REVISION |
Decimal counter | Revision of the selected page state. An absent page has revision 0. Use it together with the page and source identifiers. |
OP47_UPDATED |
true or false
|
Indicates a page-state or selection change on the current frame. |
OP47_CLEARED |
true or false
|
Indicates page erasure or an unavailable selected page. An erasure may be accompanied by newly received text, so inspect OP47_TEXT as well. |
Decoder configuration and property prefixes
Configure the source through PropsSet.
Use the property names directly in MFormats. For MPlatform, prefix them with:
file::onMFile.object::onMLive.
For example, page selection uses teletext_page in MFormats, file::teletext_page on MFile, and object::teletext_page on MLive.
| Property | Type / OP-47 default | Description |
|---|---|---|
op47.decode |
Boolean / true
|
Enables page assembly and text decoding for reader and Blackmagic capture inputs. Disabling it clears decoded output while retaining raw ANC. |
teletext_page |
Hexadecimal page number / 0
|
0 automatically chooses a subtitle page. An explicit value, such as 888, requests that page even if it has not arrived yet. This default applies to OP-47, not every Teletext backend. |
op47.anc_stream |
Integer / -1
|
Reader-only absolute source stream index. With -1, the decoder selects the first ANC stream that produces pages. Other streams are not merged into that page catalog. Not applicable to capture. |
op47.subtitles |
Boolean / false
|
Enables SUB_TEXT and SUB_XML events for showing, updating and hiding projected subtitles. Turning it off after displaying a subtitle produces a hide event. |
op47.experimental_snapshots |
Boolean / false
|
Enables binary OP47_PAGE and OP47_CATALOG data through MFDataGet. These native layouts are experimental rather than a stable public ABI. Prefer the string fields for application text processing. |
Set the options before opening the file or starting capture for predictable initial behavior.
Settings can also be changed during processing. However, frames already buffered by a reader retain their earlier results. Seeking clears assembled pages but retains the selected ANC stream; reopening resets stream selection. Capture signal loss also clears assembled pages.
Subtitle event metadata
When op47.subtitles=true, the decoder can produce the following strings:
| String ID | Format | Description |
|---|---|---|
SUB_TEXT |
Unicode text | Projected subtitle text. Empty for a hide event. |
SUB_XML |
XML | Subtitle event containing a start_time in seconds, text position and an optional confirmed lang. A hide event contains hide_text=true. |
These are change events, not a complete subtitle event repeated on every frame.
The projected position is derived from Teletext rows. This representation does not preserve the complete Teletext cell grid.
Page language and character set
A Teletext character set can serve several languages. Therefore, the decoder does not use character-set information alone to populate OP47_LANGUAGE.
For reader inputs, language is returned only when the selected ANC stream’s metadata explicitly associates it with the page. File-level and audio-track language declarations are not used as substitutes.
The recognized metadata forms are:
teletext_page_languages="888=eng;801=deu"or the following pair:
teletext_page="888"
language="eng"Page identifiers use three hexadecimal digits; language codes contain two or three letters.
These fields describe source metadata. They are not top-level reader options that detect or assign a page language. If the source provides no matching declaration, an empty OP47_LANGUAGE is expected even when the text is decoded successfully.
Use OP47_CHARSET_CANDIDATES as character-set information only.
MFormats: reading metadata in the frame loop
This example uses MFORMATSLib, requests page 888, and reads a bounded number of frames. Choose a frame count long enough for the source’s page transmission cycle.
static void ReadOp47(String SourcePath, Int32 FrameCount)
{
MFReaderClass Reader = new MFReaderClass();
try
{
Reader.PropsSet("experimental.mfcodecs", "true");
Reader.ReaderOpen(SourcePath, "op47.decode=true teletext_page=888");
for (Int32 Index = 0; Index < FrameCount; Index++)
{
MFFrame Frame = null;
try
{
Reader.SourceFrameGet(10000000, out Frame, "");
if (Frame == null)
{
break;
}
Frame.MFStrGet("OP47_PAGE_LIST", out String Pages);
Frame.MFStrGet("OP47_PAGE_NUMBER", out String Page);
Frame.MFStrGet("OP47_TEXT", out String Text);
Frame.MFStrGet("OP47_LANGUAGE", out String Language);
Console.WriteLine($"Pages: {Pages}; selected: {Page}; language: {Language}");
if (!String.IsNullOrEmpty(Text))
{
Console.WriteLine(Text);
}
// Pass Frame to a configured receiver here if required.
}
finally
{
if (Frame != null)
{
Marshal.ReleaseComObject(Frame);
}
}
}
}
finally
{
try
{
Reader.ReaderClose();
}
finally
{
Marshal.ReleaseComObject(Reader);
}
}
}For Blackmagic capture through MFLive, select the new backend before creating MFLiveClass:
[HKEY_CURRENT_USER\Software\Medialooks\MFormats\MFLive]
bmd.new_api = trueMFLive reads this setting while constructing its device list. Calling PropsSet("bmd.new_api", "true") after object creation does not by itself rebuild that list.
Before selecting and starting the device, configure capture and decoding:
live.PropsSet("vanc.capture", "true");
live.PropsSet("vanc.capture_anc", "true");
live.PropsSet("op47.decode", "true");
live.PropsSet("teletext_page", "888");Then retrieve frames through SourceFrameGet and inspect the same OP47_* strings.
MPlatform: reading metadata in a source callback
Use the normal connected-object playback or capture workflow and inspect metadata inside OnFrameSafe.
The following fragments use MPLATFORMLib and System.Runtime.InteropServices. They assume that the application owns a MFileClass instance named file.
Configure it before opening the source:
file.PropsSet("file::experimental.mfcodecs", "true");
file.PropsSet("file::op47.decode", "true");
file.PropsSet("file::teletext_page", "888");
file.PropsSet("object::on_frame.data", "true");
file.OnFrameSafe += OnOp47Frame;
file.FileNameSet(SourcePath, "");
file.FilePlayStart();Read the fields in the callback:
void OnOp47Frame(String ChannelId, Object FrameObject)
{
try
{
IMFFrame Frame = (IMFFrame)FrameObject;
Frame.MFStrGet("OP47_PAGE_LIST", out String Pages);
Frame.MFStrGet("OP47_PAGE_NUMBER", out String Page);
Frame.MFStrGet("OP47_TEXT", out String Text);
Frame.MFStrGet("OP47_LANGUAGE", out String Language);
// Copy the strings into application state.
// Perform longer processing outside this callback.
}
finally
{
if (FrameObject != null)
{
Marshal.ReleaseComObject(FrameObject);
}
}
}Keep the callback short. At shutdown, close the source, detach the handler and release the application-owned object.
For an application without a Windows message loop, configure event delivery through object::events.use_window=false.
For Blackmagic MLive, select the backend before device enumeration and configure the following before selecting and starting capture:
live.PropsSet("object::bmd.new_api", "true");
live.PropsSet("object::vanc.capture", "true");
live.PropsSet("object::vanc.capture_anc", "true");
live.PropsSet("object::op47.decode", "true");
live.PropsSet("object::teletext_page", "888");
live.PropsSet("object::on_frame.data", "true");
live.OnFrameSafe += OnOp47Frame;Troubleshooting and supported scope
No discovered pages: verify that the file contains a supported SMPTE ST 436 ANC stream, or that Blackmagic ANC capture is enabled. The presence of
ANC.Line.Nstrings does not by itself establish that their payload contains valid OP-47.Selected page has no text: inspect
OP47_PAGE_LISTand process enough frames for the requested page to arrive.OP47_PAGE_NUMBERcan report a request before the page is received. CheckOP47_CLEAREDandOP47_UPDATEDtogether with the text.Language is empty: check for explicit page-language metadata on the selected ANC stream. Character-set candidates cannot confirm the language.
Several subpages exist: the decoder retains the latest subpage for each page number.
Rendering requirements: the string interface provides text and page state. It does not provide complete Teletext Level 2.5/3.5 rendering or OP-47 encoding.
Passthrough verification: decoding retains raw ANC, but reading text does not configure hardware output or confirm successful SDI transmission. Configure the renderer and verify the received signal separately.
Still have questions?
Tell us what didn’t work or what you’d like clarified.