Triggers detection
MPlatform SDK
You can detect SCTE-35 triggers embed into local files or network streams with MPlatform SDK. For detection, you should use OnEvent events. MFile and MPlaylist objects support a special event - "SCTE-35". The event is raised the moment an SCTE-35 trigger has been received. As a parameter bsEventParam, the event has a parsed SCTE-35 message.
void m_objFile_OnEvent(string bsChannelID, string bsEventName, string bsEventParam, object pEventObject) { if (bsEventName == "SCTE-35") { string strSCTE35_Msg = bsEventParam; // manage a playback based on the information } }
In general, OnEvent and OnEventSafe events are not synchronous with the main object - they are raised in a separated thread to not affect playback. But in the case of SCTE-35 triggers, time is critical. So you should set the event to be synchronous. For this, you should set "on_event.sync" property to "true" via the system registry or with the PropsSet method.
For example, for MFile:
m_objFile.PropsSet("object::on_event.sync", "true");
MFormats SDK
With MFReader object you can detect SCTE-35 triggers by checking the data of a received MFFrame object with MFStrGet method:
MFFrame pFrame; m_objMFReader.SourceFrameGetByNumber(_nFrameNumber, -1, out pFrame, ""); // Get next frame from file string strTrigger; pFrame.MFStrGet("SCTE-35", out strTrigger); if (!string.IsNullOrEmpty(strTrigger)) { MessageBox.Show(strTrigger); // process the received data }
You can use a frame-based approach in MPlatform SDK too. For this, you should use OnFrame or OnFrameSafe events:
private void M_objFile_OnFrameSafe(string bsChannelID, object pMFrame) { string strTriggers; (pMFrame as IMFFrame).MFStrGet("SCTE-35", out strTriggers); if (!string.IsNullOrEmpty(strTriggers)) { MessageBox.Show(strTriggers); } }
Example of a trigger
<SpliceInfoSection protocolVersion='0' ptsAdjustment='3929533022' tier='4095'> <TimeSignal> <SpliceTime ptsTime='4668253151'/> </TimeSignal> <SegmentationDescriptor segmentationEventId='1' segmentationEventCancelIndicator='0' segmentationTypeId='1' segmentNum='1' segmentsExpected='1'> <SegmentationUpid segmentationUpidType='1'>000093551531446</SegmentationUpid> </SegmentationDescriptor> </SpliceInfoSection>
The code for SCTE-104 triggers detection is very similar to SCTE-35. The only difference is that you should check for "SCTE-104" string in frames.
Triggers insertion
With PropsSet method for both SDKs:
(myWriter as IMProps).PropsSet("embed_scte35", "true");
Also, the same property could be set via MWriter/MFWriter config string
Example:
format='dvb' protocol='udp://' embed_scte35='true' video::codec='mpeg2video' video::b='5M' audio::codec='aac'
The insertion of triggers should be processed on a frame basis, so it is more MFormats-like style.
The "embed_scte35" attribute is supported for TS files and UDP, DVB, SRT, HLS protocols.
MPlatform SDK
To process frames, you should use OnFrame or OnFrameSafe events. And the events should be synchronous to update a frame on its pipeline:
m_objFile.PropsSet("object::on_frame.sync", "true");
Then within the OnFrame event, you should use MFStrSet method using the XML configuration of a trigger you need to insert. Let's use the example of a trigger from the above.
private void M_objFile_OnFrameSafe(string bsChannelID, object pMFrame) { string strTriggers; (pMFrame as IMFFrame).MFStrSet("SCTE-35", strTriggers); }
A modified frame will be encoded by MWriter object according to your encoding settings, e.g. UDP stream or TS file.
MFormats SDK
The same approach with MFStrSet method is correct for MFormats SDK:
myFrame.MFStrSet("SCTE-35", strTriggers);
Insertion of the SCTE-104 triggers is similar -- you need an XML structure of the trigger to put into a frame that you later send to the output device.
Here is an example of the structure:
single_operation_message
<SCTE104 line=12>
<single_operation_message>
<opID> 1 </opID>
<result> 0 </result>
<result_extension> 0 </result_extension>
<protocol_version> 1.1 </protocol_version>
<AS_index> 1 </AS_index>
<message_number> 2 </message_number>
<DPI_PID_index> 3 </DPI_PID_index>
<data> data string </data>
</single_operation_message>
</SCTE104>
multiple_operation_message:
<SCTE104 line=12>
<multiple_operation_message>
<protocol_version> 1 </protocol_version>
<AS_index> 0 </AS_index>
<message_number> 1 </message_number>
<DPI_PID_index> 1 </DPI_PID_index>
<SCTE35_protocol_version> 1</SCTE35_protocol_version>
<timestamp>
<time_type> 2 </time_type>
<hours>16</hours>
<minutes>50</minutes>
<seconds>37</seconds>
<frames>4</frames>
</timestamp>
<ops>
<op>
<ID>0</ID>
<data>mydata</data>
</op>
<op>
<ID>256</ID>
<data>15003</data>
</op>
</ops>
</multiple_operation_message>
</SCTE104>
The structure is used only on the input side as internally the triggers are simple ANC packets.
The insertion is
pFrame.MFStrSet("SCTE-104", str104Single);
Here is an example of a received trigger:
Transcoding of triggers
If a source contains SCTE-35 triggers (MFReader or MFile, for instance) then the triggers will be encoded by default without any operations - just enable embedding the triggers with the "embed_scte35" property.