void IMFAsyncCallback.Invoke(IMFAsyncResult pResult) { IMFMediaEvent pEvent = null; MediaEventType meType = MediaEventType.MEUnknown; // Event type int hrStatus = 0; // Event status MFTopoStatus TopoStatus = MFTopoStatus.Invalid; // Used with MESessionTopologyStatus event. try { // Get the event from the event queue. m_pSession.EndGetEvent(pResult, out pEvent); // Get the event type. pEvent.GetType(out meType); // Get the event status. If the operation that triggered the event did // not succeed, the status is a failure code. pEvent.GetStatus(out hrStatus); TRACE(string.Format("Media event: " + meType.ToString())); // Check if the async operation succeeded. if (Succeeded(hrStatus)) { // Switch on the event type. Update the internal state of the CPlayer as needed. switch (meType) { case MediaEventType.MESessionTopologyStatus: // Get the status code. int i; pEvent.GetUINT32(MFAttributesClsid.MF_EVENT_TOPOLOGY_STATUS, out i); TopoStatus = (MFTopoStatus)i; switch (TopoStatus) { case MFTopoStatus.Ready: OnTopologyReady(pEvent); break; default: // Nothing to do. break; } break; case MediaEventType.MESessionStarted: OnSessionStarted(pEvent); break; case MediaEventType.MESessionPaused: OnSessionPaused(pEvent); break; case MediaEventType.MESessionClosed: OnSessionClosed(pEvent); break; case MediaEventType.MEEndOfPresentation: OnPresentationEnded(pEvent); break; } } else { // The async operation failed. Notify the application NotifyError(hrStatus); } } finally { // Request another event. if (meType != MediaEventType.MESessionClosed) { m_pSession.BeginGetEvent(this, null); } SafeRelease(pEvent); } }
private static HResult RunMediaSession(IMFMediaSession mediaSession) { HResult hr = S_OK; bool receiveSessionEvent = true; while (receiveSessionEvent) { HResult hrStatus = S_OK; IMFMediaEvent mediaEvent = null; MediaEventType eventType = MediaEventType.MEUnknown; MFTopoStatus topoStatus = MFTopoStatus.Invalid; hr = mediaSession.GetEvent(MFEventFlag.None, out mediaEvent); if (Succeeded(hr)) { hr = mediaEvent.GetStatus(out hrStatus); } if (Succeeded(hr)) { hr = mediaEvent.GetType(out eventType); } if (Succeeded(hr) && Succeeded(hrStatus)) { switch (eventType) { case MediaEventType.MESessionTopologySet: Debug.WriteLine("MediaSession:TopologySetEvent"); break; case MediaEventType.MESessionTopologyStatus: Debug.WriteLine("MediaSession:TopologStatusEvent"); hr = mediaEvent.GetUINT32(MF_EVENT_TOPOLOGY_STATUS, out int topoStatusInt); if (Succeeded(hr)) { topoStatus = (MFTopoStatus)topoStatusInt; switch (topoStatus) { case MFTopoStatus.Ready: Debug.WriteLine("MediaSession:TopologyStatus: MFTopoStatus.Ready"); hr = mediaSession.Start(); break; default: Debug.WriteLine("MediaSession:TopologyStatus: MFTopoStatus." + topoStatus); break; } } break; case MediaEventType.MESessionClosed: Debug.WriteLine("MediaSession:SessionClosedEvent"); receiveSessionEvent = false; break; case MediaEventType.MESessionStopped: Debug.WriteLine("MediaSession:SesssionStoppedEvent"); hr = mediaSession.Stop(); break; default: Debug.WriteLine("MediaSession:Event: " + eventType); break; } mediaEvent = null; if (Failed(hr) || Failed(hrStatus)) { receiveSessionEvent = false; } } } return(hr); }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// Handles events reported by the media session TantaAsyncCallbackHandler /// </summary> /// <param name="sender">the object sending the event</param> /// <param name="mediaEvent">the event generated by the media session. Do NOT release this here.</param> /// <param name="mediaEventType">the eventType, this is just an enum</param> /// <history> /// 01 Nov 18 Cynic - Originally Written /// </history> private void HandleMediaSessionAsyncCallBackEvent(object sender, IMFMediaEvent pEvent, MediaEventType mediaEventType) { LogMessage("Media Event Type " + mediaEventType.ToString()); switch (mediaEventType) { case MediaEventType.MESessionTopologyStatus: // Raised by the Media Session when the status of a topology changes. // Get the topology changed status code. This is an enum in the event int i; HResult hr = pEvent.GetUINT32(MFAttributesClsid.MF_EVENT_TOPOLOGY_STATUS, out i); if (hr != HResult.S_OK) { throw new Exception("HandleMediaSessionAsyncCallBackEvent call to pEvent to get the status code failed. Err=" + hr.ToString()); } // the one we are most interested in is i == MFTopoStatus.Ready // which we get then the Topology is built and ready to run HandleTopologyStatusChanged(pEvent, mediaEventType, (MFTopoStatus)i); break; case MediaEventType.MESessionStarted: // Raised when the IMFMediaSession::Start method completes asynchronously. // PlayerState = TantaEVRPlayerStateEnum.Started; break; case MediaEventType.MESessionPaused: // Raised when the IMFMediaSession::Pause method completes asynchronously. // PlayerState = TantaEVRPlayerStateEnum.Paused; break; case MediaEventType.MESessionStopped: // Raised when the IMFMediaSession::Stop method completes asynchronously. break; case MediaEventType.MESessionClosed: // Raised when the IMFMediaSession::Close method completes asynchronously. break; case MediaEventType.MESessionCapabilitiesChanged: // Raised by the Media Session when the session capabilities change. // You can use IMFMediaEvent::GetValue to figure out what they are break; case MediaEventType.MESessionTopologySet: // Raised after the IMFMediaSession::SetTopology method completes asynchronously. // The Media Session raises this event after it resolves the topology into a full topology and queues the topology for playback. break; case MediaEventType.MESessionNotifyPresentationTime: // Raised by the Media Session when a new presentation starts. // This event indicates when the presentation will start and the offset between the presentation time and the source time. break; case MediaEventType.MEEndOfPresentation: // Raised by a media source when a presentation ends. This event signals that all streams // in the presentation are complete. The Media Session forwards this event to the application. // we cannot sucessfully .Finalize_ on the SinkWriter // if we call CloseAllMediaDevices directly from this thread // so we use an asynchronous method Task taskA = Task.Run(() => CloseAllMediaDevices()); // we have to be on the form thread to update the screen ThreadSafeScreenUpdate(this, false, "Done"); break; case MediaEventType.MESessionRateChanged: // Raised by the Media Session when the playback rate changes. This event is sent after the // IMFRateControl::SetRate method completes asynchronously. break; default: LogMessage("Unhandled Media Event Type " + mediaEventType.ToString()); break; } }