Transmitting CC608 via ANC packets
Our SDKs have tools for inserting custom metadata or ancillary data (ANC packets) inside each individual frame. After that, the frames might be sent to SDI output. And one of the possible way to use ANC packets is inserting closed caption data inside these packets. This article covers basic principles and approaches how to implement such a functionality in your solutions.
To achieve this goal, the following steps have to be performed:
- Configure a receiving application for capturing ANC data, which are received from SDI output.
- Design a sender application and implement a logic which sends CC608 ANC data every frame until a transmitted line of text is fully transmitted.
Speaking about the second paragraph, there are four features to which attention should be paid:
- All the CC608 commands and data (one pair of chars) inside ANC packets might be stored inside 2 bytes (16 bits). They can be stored, for instance, into Uint16 variables.
- The transmitting process starts with sending initializing commands.
- It possible to send only 2 chars or 1 command of CC per 1 frame.
- By default, empty CC608 ANC data (0x8080) must be sent every frame if required by the hardware.
More information about CC608 and their structure can be found here -> https://en.wikipedia.org/wiki/EIA-608
Preparing the receiving side
First of all, it's needed to enable receiving ANC packet by SDI cards. To do that, follow this path in your registry "Computer\HKEY_CURRENT_USER\SOFTWARE\Medialooks\MFormats\MFLive\BMD" and set these three properties as "true":
The last folder of the path is defined the SDI card, what you use. In this article, BMD card is used. If you have, for example, BlueFish card, the path will be: "Computer\HKEY_CURRENT_USER\SOFTWARE\Medialooks\MFormats\MFLive\BF"
For these other cards that three properties might have other names and they are true by default.
The same can be done through the code:
MFormats: // For receiving side: |
MPlatform: // For receiving side: |
Also don't forget to make sure that the SDK shows CC608, not CC708, if you want to display the received closed captions:
"Computer\HKEY_CURRENT_USER\SOFTWARE\Medialooks\MCCDisplay" -> cc_type = 608
Implementing the sending side
When we have prepared the receiving application, it's needed to study how to put custom CC608 data into the ANC packets inside the frames for transmitting. Since MFormats SDK works on a frame level, we can modify them in any way we want in any place of the code we have an access the frames. But if you work with MPlatform SDK, it's needed to attach OnFrameSafe event on an MRendererClass instance and enable frame data modifying:
MPlatform:
// Attaching OnFrameSafe event to the renderer and allowing to modify data there:
m_objRenderer.OnFrameSafe += m_objRenderer_OnFrameSafe;
m_objRenderer.PropsSet("on_frame.sync", "true");
m_objRenderer.PropsSet("on_frame.data", "true");
private void m_objRenderer_OnFrameSafe(string bsChannelID, object pMFrame)
{
// ... Here should be the logic of inserting CC608 ANC data.
System.Runtime.InteropServices.Marshal.ReleaseComObject(pMFrame); // You should call these methods to release MFrame object
GC.Collect(); // Force CG to collect the garbage (optional)
}
With this code, we get an access the individual frames of the SDK's object. To get more information about events in MPlatform can be found in this article -> https://support.medialooks.com/hc/en-us/articles/360000209812-Events
Now, the main part of it. To transmit the custom CC608 through the ANC packet with a frame, it's needed to declare and define the data for transiting, insert the data into the frame and put this frame into the MFRendererClass / MRendererClass instance. The following code inserts empty CC608 data into ANC packets inside the frames.
MFormats & MPlatforms:
// Inserting the ANC data into the frame:
UInt16 dwBytes = 0x8080; // Empty ANC packet.
IntPtr pdwBytes = new IntPtr(dwBytes);
(pMFrame as IMFFrame).MFDataSet("C608", 0, (long)pdwBytes);
The same can be done through a byte array:
// Inserting the ANC data into the frame:
byte[] dwBytes = { 0x80, 0x80 };
IntPtr pdwBytes = Marshal.AllocHGlobal(dwBytes.Length);
Marshal.Copy(dwBytes, 0, pdwBytes, dwBytes.Length);
(pMFrame as IMFFrame).MFDataSet("C608", dwBytes.Length, (long)pdwBytes);
MFDataSet() method sets both the CC608 commands and data. In spite of the fact, that out SDKs ignore the empty CC608 data inside ANC packets, we still recommend to send them for a better compatibility with old equipment if you use CC608 but there is no data to transmit.
Now, let's look at an example of passing "Hello World!" string. As it is described in the beginning of the article, the transmitting process starts with sending the commands of the initializing. All the commands consist of 2 bytes. The first low byte defines CC channel (0x14 for the first CC channel), and the second byte defines the command itself. So, to start the transmitting, two byte sequences have to be sent (1st command - Roll up 3 (scroll size) - 0x26, 2nd command -> Carriage return (scroll lines up) - 0x2D).
1st byte sequence: 0x2614 - The first CC channel - 0x14, Roll up 3 (scroll size) - 0x26
2nd byte sequence: 0x2D14 - The first CC channel - 0x14, Carriage return (scroll lines up) - 0x2D
When we have it done, the receiver side is ready for receiving the characters data itself. We can send only 2 chars per 1 frame. So that, for passing "Hello World!" string (12 chars in total), it's needed 6 CC608 ANC packets. So that, to transmit this string, the following CC608 data have to be packed inside the ANC packet:
0x6548 - He (0x65 - e, 0x48 - H)
0x6C6C - ll (0x6c - l)
0x206F - o (0x20 - gap, 0x6F - o)
0x6F57 - Wo (0x6F - 0, 0x57 - W)
0x6C72 - rl (0x6C - l, 0x72 - r)
0x2164 - d! (0x21 - !, 0x64 - d)
On the frame level it looks like that:
Now, the only thing to do is designing the code which automatically parses our strings to be transited, into byte sequence and transmits all the necessary commands and char data for sending the line of CC608. At the end of this article, two samples are attached for the transmission of custom CC608 through the ANC packets, both for MFormats SDK and for MPlatform SDK.
Using Sample File Writing "C:\Program Files (x86)\Medialooks\MFormats SDK\Samples\C#\Sample File Writing\bin\x86\Debug\Sample File Writing.exe" and the attached samples, you can observe how it works. Feel free to study them for a better understanding but note, that those samples are basics ones and might not be suitable for production. They only shows the principles of CC608 transmitting via ANC packets.
Transmitting the string:
Besides the text, you can also send commands for CC management. For example, byte 0x21 overwrites last char (byte 0x14 is needed for addressing to the first CC channel). So that, if you send 0x2114 (0x21 - backspace (overwrite last char), 0x14 - the first CC channel ), the last char is overwritten:
In the similar way, byte 0x2D is in charge of carriage returning (scroll lines up):
The complete list of the commands and the char hex codes can be found here -> https://en.wikipedia.org/wiki/EIA-608