Events help you to monitor what happens with objects that you operate. There are 2 types of events:
- OnFrame (OnFrameSafe) - raises on each processed frame. Available only in MPlatform SDK. With MFormats SDK you control each frame separately so there is no need in such events.
- OnEvent (OnEventSafe) - raises when each significant event happens with an object.
Difference between -Safe events and usual events
The difference between OnEventSafe and OnFrameSafe events is noticeable only with .Net-based languages, e.g. C# and VB.Net. The -Safe events were implemented to avoid objects handles leakage specific to the way .Net technology works with COM objects.
For Delphi and C++ you should use OnEvent and OnFrame events through IMCallback interfaces. See the article about memory release issues for additional information.
How to implement events for different languages?
C#
//Form_Load method //initialize events
m_objPlaylist.OnEventSafe += new MPLATFORMLib.IMEventsEvent_OnEventSafeEventHandler(m_objPlaylist_OnEvent);
m_objPlaylist.OnFrameSafe += new MPLATFORMLib.IMEventsFrame_OnFrameSafeEventHandler(m_objPlaylist_OnFrame); void m_objPlaylist_OnEvent(string bsChannelID, string bsEventName, string bsEventParam, object pEventObject) { if (bsEventName == "EOF") { int nIndex, nNextIndex; double dblFileTime, dblListTime; m_objPlaylist.PlaylistPosGet(out nIndex, out nNextIndex, out dblFileTime, out dblListTime); } }
C++
static HRESULT OnEvent(LONGLONG lCallbackCookie, BSTR bsChannelID, BSTR bsEventName, BSTR bsEventParam, IUnknown* pEventObject); static HRESULT OnFrame(LONGLONG llCallbackUserData, BSTR bsChannelID, IUnknown* pMFrame);
Note that for C++ onFrame event you should set "object::on_frame.sync" property to "true"
HRESULT CLiveSourceSampleDlg::OnEvent(LONGLONG lCallbackCookie, BSTR bsChannelID, BSTR bsEventName, BSTR bsEventParam, IUnknown* pEventObject) return S_OK; }; HRESULT CLiveSourceSampleDlg::OnFrame(LONGLONG llCallbackUserData, BSTR bsChannelID, IUnknown* pMFrame) { return S_OK; }; For LiveSource sample: LONGLONG cookie = 0; LONGLONG onEvt = (LONGLONG)&(CLiveSourceSampleDlg::OnEvent); LONGLONG onFrm = (LONGLONG)&(CLiveSourceSampleDlg::OnFrame); m_objLive->ObjectCallbackSetFunc(onEvt, onFrm, (LONG_PTR)cookie);
Delphi
// 1. Create a custom class TEvents TEvents = class (TInterfacedObject, IMCallback) function OnEvent(lCallbackCookie: LONG_PTR; const bsChannelID: WideString; const bsEventName: WideString; const bsEventParam: WideString; const pEventObject: IUnknown): HResult; stdcall; function OnFrame(lCallbackCookie: LONG_PTR; const bsChannelID: WideString; const pMFrame: IUnknown): HResult; stdcall; end; // 2. On Form Load procedure create a TEvents class object m_objEvents := TEvents.Create(); // 3. Start to listen this events with ObjectCallbackSet method m_pObject.ObjectCallbackSet(m_objEvents, cookie); // 4. Create these functions function TEvents.OnEvent(lCallbackCookie: LONG_PTR; const bsChannelID: WideString; const bsEventName: WideString; const bsEventParam: WideString; const pEventObject: IUnknown): HResult; stdcall; var nRows, nIndex, nNextIndex : integer; dblFileTime, dblListTime : Double; begin if (bsEventName = 'EOF') then begin nRows := Form2.dataGridViewFiles.RowCount; Form2.m_objPlaylist.PlaylistPosGet(nIndex, nNextIndex, dblFileTime, dblListTime); if (nRows > 2) and (nIndex <= nRows - 2) then Form2.dataGridViewFiles.Row := nIndex + 1; end; end; function TEvents.OnFrame(lCallbackCookie: LONG_PTR; const bsChannelID: WideString; const pMFrame: IUnknown): HResult; stdcall; begin end;
Please also note that for HTML plugin in Delphi you should use the IMFObject to set callback both in the MPlatform and MFormats.
m_objOverlayHTML := CreateComObject(CLASS_MFOverlayHTML) as IMFBrowser;
(m_objOverlayHTML as IMFObject).MFCallbackSet(m_objEvents, cookie);
Windows Service events
delegate void CallbackDelegateEvent(long llCallbackUserData, Int32 bsChannelID, Int32 bsEventName, Int32 bsEventParam, Int32 pEventObject); delegate void CallbackDelegateFrame(long llCallbackUserData, Int32 bsChannelID, Int32 pFrame); // --------------------------------------- OnEvent ----------------------------------------------------------- // GCHandle gchCallbackDelegateOnEvent; void OnEvent_as_Callback() { eventLog1.WriteEntry("OnEvent_as_Callback starting..."); CallbackDelegateEvent callbackDelegate = TheCallbackEvent; IntPtr callbackDelegatePointer = Marshal.GetFunctionPointerForDelegate(callbackDelegate); GC.Collect(); gchCallbackDelegateOnEvent = GCHandle.Alloc(callbackDelegate); // !!!! m_objFile.ObjectCallbackSetFunc(callbackDelegatePointer.ToInt64(), 0, 0); GC.Collect(); eventLog1.WriteEntry("OnEvent_as_Callback done."); } public void TheCallbackEvent(long llCallbackUserData, int bsChannelID, int bsEventName, int bsEventParam, int pEventObject) { // Convert this pointer object pThis = ((GCHandle)new IntPtr(llCallbackUserData)).Target; // Convert string string strChannel = Marshal.PtrToStringBSTR(new IntPtr(bsChannelID)); // Convert string string strEventName = Marshal.PtrToStringBSTR(new IntPtr(bsEventName)); // Convert string string strEventParam = Marshal.PtrToStringBSTR(new IntPtr(bsEventParam)); eventLog1.WriteEntry("OnEvent!!! " + llCallbackUserData + " " + strChannel + " " + strEventName + " " + strEventParam); } // --------------------------------------- OnFrame ----------------------------------------------------------- // GCHandle gchCallbackDelegateOnFrame; void OnFrame_as_Callback() { eventLog1.WriteEntry("OnFrame_as_Callback starting..."); CallbackDelegateFrame callbackDelegateFrame = TheCallbackFrame; IntPtr callbackDelegatePtr = Marshal.GetFunctionPointerForDelegate(callbackDelegateFrame); IntPtr callbackThisPtr = (IntPtr)GCHandle.Alloc(this); GC.Collect(); gchCallbackDelegateOnFrame = GCHandle.Alloc(callbackDelegateFrame); m_objFile.ObjectCallbackSetFunc(0, callbackDelegatePtr.ToInt64(), callbackThisPtr.ToInt64()); GC.Collect(); eventLog1.WriteEntry("OnFrame_as_Callback done."); } public void TheCallbackFrame(long llCallbackUserData, Int32 bsChannelID, Int32 pFrame32) { // Convert this pointer object pThis = ((GCHandle)new IntPtr(llCallbackUserData)).Target; // Convert string string strChannel = Marshal.PtrToStringBSTR(new IntPtr(bsChannelID)); // Convert pFrame IMFFrame pMFrame = (IMFFrame)Marshal.GetObjectForIUnknown(new IntPtr(pFrame32)); // Check frame M_TIME mTime; pMFrame.MFTimeGet( out mTime ); eventLog1.WriteEntry("OnFrame!!! " + pThis + " " + strChannel + " " + mTime.tcFrame.nExtraCounter); }
Available events for objects
MFile
The bsChannelID shows a path to the currently initialized file.
- "start" - raises the moment playback is started.
bsEventParam:
"" - simple start of playback.
"loop" - restart of the file if it is in a "loop" state. - "pause" - raises the time you set the object in pause state by the FilePlayPause method.
bsEventParam is a duration of the pause. - "EOF" - raises when the file reaches its end.
bsEventParam:
"stop" - the file stops at the end.
"loop" - the file is in "loop" state. - "stop" - raises the time you set the object in stop state by the FilePlayStop method.
bsEventParam is a duration of the stop. - "connect" - raises at the moment a network stream is connected or disconnected.
bsEventParam:
"false" - the stream is disconnected.
"true" - the stream is re-connected. - "watch-dog" - raises the moment a watch-dog triggers some event.
bsEventParam:
"object-locked"
"error-access"
"file-freeze"
"file-failed"
"update"
"update-failed" - "SCTE35" - raises the moment an SCTE-35 trigger is received. As bsEventParam it uses a parsed SCTE-35 message string.
- "connect" - raises when the stream connected/diconnected.
bsEventParam:
"true" - stream connected to the object.
"false" - stream disconnected.
MLive & MFLive
- "no_signal" - raises when a source signal is lost ("No Video Signal" message appears).
Possible bsEventParam values: true (the signal is lost) and false (the signal is restored). - "format_changed" - raises the moment a source video format is changed. bsEventParam shows the name of a new video format.
- "SCTE35" - raises the moment an SCTE-35 trigger is received. As bsEventParam it uses a parsed SCTE-35 message string.
- "SCTE104" - raises the moment an SCTE-104 trigger is received. As bsEventParam it uses a parsed SCTE-104 message string.
MPlaylist
- "switch" - raises the moment playlist switches from one item to another.
bsEventParam:
"from" - indicates a previous item (a path to a file or an object name) as the bsChannels parameter.
"to" - indicates the item (a path to a file or an object name) as the bsChannels parameter. - "playlist-command" - raises the moment an MPlaylist executes a command. Indicates a command as the bsChannels parameter.
- "playlist_add" - raises the moment you add a new item with the PlaylistAdd method. Shows a name of the MPlaylist object as the bsChannels parameter.
bsEventParam is a target index of a new item. - "playlist_remove" - raises the moment you remove an item with the PlaylistRemove or the PlaylistRemoveByIndex methods. Shows a name of the MPlaylist object as the bsChannels parameter.
bsEventParam is a target index of a removed item. - "EOL" - raises the moment the playlist is over. Shows a name of the MPlaylist object as the bsChannels parameter.
- "pause" - raises the time you set the object in pause state by the FilePlayPause method.
bsEventParam is a duration of the pause. - "start" - raises the moment the object is started with the ObjectStart method.
- "stop" - raises the time you set the object in stop state by the FilePlayStop method.
bsEventParam is:
a duration of the stop
"stop-done" - raises when stop time is over and playback is resumed.
"error-OutOfMemory" - raises when the playlist is stopped because of an OutOfMemory exception. - "EOF" - raises the moment an item is over.
- "break-command" - raises the moment a break command is executed.
bsEventParam is:
a position of a break
"error-execute" - indicates that command can't be executed. - "break-start" - raises the moment a break is started.
bsEventParam is:
a position of a break
"error-start" - indicates that a break can't be started. - "break-done" - raises the moment a break is over.
- "SCTE35" - raises the moment an SCTE-35 trigger is received. As bsEventParam it uses a parsed SCTE-35 message string.
- "connect" - raises when the stream connected/diconnected.
bsEventParam:
"true" - stream connected to the object.
"false" - stream disconnected.
MWriter
bsChannelID is the name of an object.
- "file-close" - raises the moment when the encoded file is available for usage by the system. Available for both MWriter and MFWriter object.
bsEventParam is a path to the encoded file. - "error-abort" - raises on any error during recorder. Available for MFWriter only.
bsEventParam can be "disk-full" (raises when the target disk is full) or an error code. - "switch" - raises the moment you switch from one destination to another.
bsEventParam is a path to the encoded file. - "start" - raises the moment the encoding is started.
bsEventParam is a path to the encoded file. - "stop" - raises the moment you stop the encoding.
bsEventParam is a path to the encoded file. - "file-close-info" - raises the moment when the encoded file is available for usage by the system.
bsEventParam is information about a file. - "disk-full" - raises when the target disk is full.
- "end-of-media" - raises when the end of a source is reached.
- "max-switch" - raises when the maximal amount of switches is reached.
MFWriter
- "file-close" - raises the moment when the encoded file is available for usage by the system. Available for both MWriter and MFWriter object.
bsEventParam is a path to the encoded file. - "error-abort" - raises on any error during recorder. Available for MFWriter only.
bsEventParam can be "disk-full" (raises when the target disk is full) or an error code.
bsChannelID is the name of an object.
MMixer
- "scene_active_set" - raises the moment you set an active scene.
bsEventParam indicates whether the active scene is set ("true", "false"). - "pause" - raises the time you set the object in pause state by the FilePlayPause method.
bsEventParam is:
duration of the pause.
"pause-done" - indicates that the pause is over
"pause-start" - indicates that the pause is started - "start" - raises the moment you start the object with the ObjectStart method.
- "stop" - raises the moment you set the object in stop state by the FilePlayStop method.
bsEventParam is a duration of the stop. - "source_disconnected" - raises when a stream is disconnected.
- "source_connected" - raises when a stream is connected back.
- "disconnect" - raises when you remove a stream with the StreamsRemove method.
- "connect" - raises when you add a stream with the StreamsAdd method.
MPreview
- "wpf_nextframe" - raises on each received frame in wpf_preview=true mode. See the article about WPF Preview for more details.