private void CloseAllMediaDevices() { HResult hr; Console.WriteLine("CloseAllMediaDevices"); // close and release our call back handler if (mediaSessionAsyncCallbackHandler != null) { // stop any messaging or events in the call back handler mediaSessionAsyncCallbackHandler.ShutDown(); mediaSessionAsyncCallbackHandler = null; } // Shut down the source reader if (StreamReader != null) { Marshal.ReleaseComObject(StreamReader); StreamReader = null; } // close the session (this is NOT the same as shutting it down) if (mediaSession != null) { hr = mediaSession.Close(); if (hr != HResult.S_OK) { // just log it Console.WriteLine("CloseAllMediaDevices call to mediaSession.Close failed. Err=" + hr.ToString()); } } // Shut down the media source if (MediaSource != null) { hr = MediaSource.Shutdown(); if (hr != HResult.S_OK) { // just log it Console.WriteLine("CloseAllMediaDevices call to mediaSource.Shutdown failed. Err=" + hr.ToString()); } Marshal.ReleaseComObject(MediaSource); MediaSource = null; } // Shut down the media session (note we only closed it before). if (mediaSession != null) { hr = mediaSession.Shutdown(); if (hr != HResult.S_OK) { // just log it Console.WriteLine("CloseAllMediaDevices call to mediaSession.Shutdown failed. Err=" + hr.ToString()); } Marshal.ReleaseComObject(mediaSession); mediaSession = null; } if (currentVideoMediaType != null) { Marshal.ReleaseComObject(currentVideoMediaType); currentVideoMediaType = null; } }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// A centralized place to close down all media devices. /// </summary> /// <history> /// 01 Nov 18 Cynic - Started /// </history> private void CloseAllMediaDevices() { HResult hr; LogMessage("CloseAllMediaDevices"); // close and release our call back handler if (mediaSessionAsyncCallbackHandler != null) { // stop any messaging or events in the call back handler mediaSessionAsyncCallbackHandler.ShutDown(); mediaSessionAsyncCallbackHandler = null; } // close the session (this is NOT the same as shutting it down) if (mediaSession != null) { hr = mediaSession.Close(); if (hr != HResult.S_OK) { // just log it LogMessage("CloseAllMediaDevices call to mediaSession.Close failed. Err=" + hr.ToString()); } } // Shut down the media source if (mediaSource != null) { hr = mediaSource.Shutdown(); if (hr != HResult.S_OK) { // just log it LogMessage("CloseAllMediaDevices call to mediaSource.Shutdown failed. Err=" + hr.ToString()); } Marshal.ReleaseComObject(mediaSource); mediaSource = null; } // Shut down the media session (note we only closed it before). if (mediaSession != null) { hr = mediaSession.Shutdown(); if (hr != HResult.S_OK) { // just log it LogMessage("CloseAllMediaDevices call to mediaSession.Shutdown failed. Err=" + hr.ToString()); } Marshal.ReleaseComObject(mediaSession); mediaSession = null; } // close the media sink if (mediaSink != null) { Marshal.ReleaseComObject(mediaSink); mediaSink = null; } }
public static void MFCreateMediaSession(IMFAttributes configuration, out IMFMediaSession mediaSession) { int result = ExternMFCreateMediaSession(configuration, out mediaSession); if (result < 0) { throw new COMException("Exception from HRESULT: 0x" + result.ToString("X", System.Globalization.NumberFormatInfo.InvariantInfo) + " (MFCreateMediaSession)", result); } }
public SimpleFastEncode() { // Create objects and bind the background worker events this.EncodeProgress = null; this.presentationClock = null; this.mediaSession = null; this.mediaSource = null; this.progressTimer = new Timer(500); this.progressTimer.Elapsed += this.ProgressTimer_Tick; }
/// <summary> /// Closes the player /// </summary> public void Close() { Marshal.FinalReleaseComObject(m_Clock); Marshal.FinalReleaseComObject(m_pDescriptor); Marshal.FinalReleaseComObject(m_Rate); Marshal.FinalReleaseComObject(m_Volume); m_Session.Shutdown(); m_Session = null; m_Eventthread.Join(); GC.SuppressFinalize(this); }
/// <summary> /// Starts the Media Session. /// </summary> /// <param name="mediaSession">A valid IMFMediaSession instance.</param> /// <param name="startPosition">The starting position for playback.</param> /// <returns>If this function succeeds, it returns the S_OK member. Otherwise, it returns another HResult's member that describe the error.</returns> public static HResult Start(this IMFMediaSession mediaSession, TimeSpan startPosition) { if (mediaSession == null) { throw new ArgumentNullException("mediaSession"); } using (PropVariant start = new PropVariant(startPosition.Ticks)) { return(mediaSession.Start(Guid.Empty, start)); } }
public void Dispose() { if (m_Session != null) { Marshal.FinalReleaseComObject(m_clock); Marshal.FinalReleaseComObject(m_rate); Marshal.FinalReleaseComObject(m_volume); m_Session.Shutdown(); m_Session = null; m_eventthread?.Join(); } GC.SuppressFinalize(this); }
// ----- Public Methods ----------------------------------------------- ////////////////////////////////////////////////////////////////////////// // Name: CPlayer // Description: Constructor // ///////////////////////////////////////////////////////////////////////// public CPlayer(IntPtr hWnd) { m_hWnd = hWnd; m_pMediaSession = null; m_pSequencerSource = null; m_pAudioRendererActivate = null; m_pPresentationClock = null; m_PresentationTimeOffset = 0; m_phnsTimePairStart = null; m_phnsTimePairEnd = null; m_State = PlayerState.PlayerCreated; m_ActiveSegment = -1; m_hCloseEvent = new AutoResetEvent(false); }
private static HResult ProcessMediaSession(string VideoFile) { HResult hr = S_OK; IMFMediaSource source = null; IMFTopology topology = null; IMFMediaSinkAlt mediaSink = null; IMFMediaSession mediaSession = null; hr = CreateMediaSource(VideoFile, out source); if (Failed(hr)) { return(hr); } hr = CreateTopology(out topology, out mediaSink, source); if (Failed(hr)) { topology = null; mediaSink = null; source = null; return(hr); } hr = MF.CreateMediaSession(null, out mediaSession); if (Failed(hr)) { topology = null; mediaSink = null; source = null; mediaSession = null; return(hr); } hr = mediaSession.SetTopology(MFSessionSetTopologyFlags.None, topology); if (Failed(hr)) { topology = null; mediaSink = null; source = null; mediaSession = null; return(hr); } hr = RunMediaSession(mediaSession); return(hr); }
public MFMediaUriPlayer(IntPtr hVideo, IntPtr hEvent) { Debug.Assert(hVideo != IntPtr.Zero); Debug.Assert(hEvent != IntPtr.Zero); m_pSession = null; m_pSource = null; m_pVideoDisplay = null; m_hwndVideo = hVideo; m_hwndEvent = hEvent; m_state = PlayerState.Ready; m_hCloseEvent = new AutoResetEvent(false); MFExtern.MFStartup(0x10070, MFStartup.Full); }
/// <summary> /// Init /// </summary> /// <param name="hVideo"></param> /// <param name="hEvent"></param> public Media(IntPtr hVideo, IntPtr hEvent) { TRACE("Media::Media"); Debug.Assert(hVideo != IntPtr.Zero); Debug.Assert(hEvent != IntPtr.Zero); m_pSession = null; m_pSource = null; m_pVideoDisplay = null; m_hwndVideo = hVideo; m_hwndEvent = hEvent; m_state = MediaState.Ready; m_hCloseEvent = new AutoResetEvent(false); MFExtern.MFStartup(MF_VERSION, MFStartup.Full); }
/// <summary> /// Resets the local graph resources to their /// default settings /// </summary> private void ResetGraphResources() { //m_graph = null; if (m_pSource != null) { Marshal.ReleaseComObject(m_pSource); } m_pSource = null; if (m_pSession != null) { Marshal.ReleaseComObject(m_pSession); } m_pSession = null; }
protected void CloseSession() { int hr; /*if (m_pVideoDisplay != null) * { * Marshal.ReleaseComObject(m_pVideoDisplay); * m_pVideoDisplay = null; * } */ if (m_pSession != null) { hr = m_pSession.Close(); MFError.ThrowExceptionForHR(hr); // Wait for the close operation to complete /*bool res = m_hCloseEvent.WaitOne(5000, true); * if (!res) * { * TRACE(("WaitForSingleObject timed out!")); * }*/ } // Complete shutdown operations // 1. Shut down the media source if (m_pSource != null) { hr = m_pSource.Shutdown(); MFError.ThrowExceptionForHR(hr); COMBase.SafeRelease(m_pSource); m_pSource = null; } // 2. Shut down the media session. (Synchronous operation, no events.) if (m_pSession != null) { hr = m_pSession.Shutdown(); Marshal.ReleaseComObject(m_pSession); m_pSession = null; } }
public CPlayer(IntPtr hVideo, IntPtr hEvent) { TRACE(("CPlayer::CPlayer")); Debug.Assert(hVideo != IntPtr.Zero); Debug.Assert(hEvent != IntPtr.Zero); m_pSession = null; m_pSource = null; m_pVideoDisplay = null; m_hwndVideo = hVideo; m_hwndEvent = hEvent; m_state = PlayerState.Ready; m_hCloseEvent = new AutoResetEvent(false); int hr = MFExtern.MFStartup(0x10070, MFStartup.Full); MFError.ThrowExceptionForHR(hr); }
private void SetFirstTopology(IMFSequencerSource pSequencerSource, IMFMediaSession pMediaSession) { IMFMediaSource pMediaSource; IMFPresentationDescriptor pPresentationDescriptor; IMFMediaSourceTopologyProvider pMediaSourceTopologyProvider; IMFTopology pTopology; pMediaSource = pSequencerSource as IMFMediaSource; // Create the presentation descriptor for the media source. int hr = pMediaSource.CreatePresentationDescriptor(out pPresentationDescriptor); MFError.ThrowExceptionForHR(hr); // Get the topology provider from the sequencer source. pMediaSourceTopologyProvider = pSequencerSource as IMFMediaSourceTopologyProvider; // Get the first topology from the topology provider. hr = pMediaSourceTopologyProvider.GetMediaSourceTopology(pPresentationDescriptor, out pTopology); MFError.ThrowExceptionForHR(hr); // Set the topology on the media session. hr = pMediaSession.SetTopology(0, pTopology); MFError.ThrowExceptionForHR(hr); }
/// <summary> /// Close a Media Session /// </summary> protected void CloseSession() { if (m_pVideoDisplay != null) { Marshal.ReleaseComObject(m_pVideoDisplay); m_pVideoDisplay = null; } if (m_pSession != null) { m_pSession.Close(); // Wait for the close operation to complete bool res = m_hCloseEvent.WaitOne(WAIT_TIMEOUT, true); if (!res) { TRACE("WaitForSingleObject Timed Out !"); } } // Complete shutdown operations // 1. Shut down the media source if (m_pSource != null) { m_pSource.Shutdown(); SafeRelease(m_pSource); m_pSource = null; } // 2. Shut down the media session. (Synchronous operation, no events.) if (m_pSession != null) { m_pSession.Shutdown(); Marshal.ReleaseComObject(m_pSession); m_pSession = null; } }
// ----- Public Methods ----------------------------------------------- ////////////////////////////////////////////////////////////////////////// // Name: CPlayer // Description: Constructor // ///////////////////////////////////////////////////////////////////////// public CPlayer(IntPtr hWnd) { m_hWnd = hWnd; m_pMediaSession = null; m_pSequencerSource = null; m_pAudioRendererActivate = null; m_pPresentationClock = null; m_PresentationTimeOffset = 0; m_phnsTimePairStart = null; m_phnsTimePairEnd = null; m_State = PlayerState.PlayerCreated; m_ActiveSegment = -1; m_hCloseEvent = new AutoResetEvent(false); }
public static extern void MFCreatePMPMediaSession( MFPMPSessionCreationFlags dwCreationFlags, IMFAttributes pConfiguration, out IMFMediaSession ppMediaSession, out IMFActivate ppEnablerActivate );
public static extern void MFCreateMediaSession( IMFAttributes pConfiguration, out IMFMediaSession ppMediaSession );
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// Gets the playback rate capabilitys for the session /// </summary> /// <param name="mediaSession">the media session. If not null, we will /// populate this object from the session</param> /// <history> /// 01 Nov 18 Cynic - Started /// </history> public bool AcquirePlayBackRates(IMFMediaSession mediaSession) { bool outBool; bool wantThinned; float supportedRate; Reset(); if (mediaSession == null) { return(false); } try { // first we acquire the thinned rates wantThinned = true; outBool = TantaWMFUtils.GetFastestRate(mediaSession, MFRateDirection.Forward, wantThinned, out supportedRate); if (outBool == true) { fastestForwardSpeedThinned = Math.Abs(supportedRate); } outBool = TantaWMFUtils.GetSlowestRate(mediaSession, MFRateDirection.Forward, wantThinned, out supportedRate); if (outBool == true) { slowestForwardSpeedThinned = Math.Abs(supportedRate); } // now test for the reverse being possible with this thinning mode outBool = TantaWMFUtils.IsRewindSupported(mediaSession, wantThinned); if (outBool == true) { reverseSpeedIsSupportedThinned = true; outBool = TantaWMFUtils.GetFastestRate(mediaSession, MFRateDirection.Reverse, wantThinned, out supportedRate); if (outBool == true) { fastestReverseSpeedThinned = Math.Abs(supportedRate); } outBool = TantaWMFUtils.GetSlowestRate(mediaSession, MFRateDirection.Reverse, wantThinned, out supportedRate); if (outBool == true) { slowestReverseSpeedThinned = Math.Abs(supportedRate); } } // next we acquire the thinned rates wantThinned = false; outBool = TantaWMFUtils.GetFastestRate(mediaSession, MFRateDirection.Forward, wantThinned, out supportedRate); if (outBool == true) { fastestForwardSpeedNonThinned = Math.Abs(supportedRate); } outBool = TantaWMFUtils.GetSlowestRate(mediaSession, MFRateDirection.Forward, wantThinned, out supportedRate); if (outBool == true) { slowestForwardSpeedNonThinned = Math.Abs(supportedRate); } // now test for the reverse being possible with this thinning mode outBool = TantaWMFUtils.IsRewindSupported(mediaSession, wantThinned); if (outBool == true) { reverseSpeedIsSupportedNonThinned = true; outBool = TantaWMFUtils.GetFastestRate(mediaSession, MFRateDirection.Reverse, wantThinned, out supportedRate); if (outBool == true) { fastestReverseSpeedNonThinned = Math.Abs(supportedRate); } outBool = TantaWMFUtils.GetSlowestRate(mediaSession, MFRateDirection.Reverse, wantThinned, out supportedRate); if (outBool == true) { slowestReverseSpeedNonThinned = Math.Abs(supportedRate); } } capabilityRequestSuccessful = true; } catch { capabilityRequestSuccessful = false; } return(CapabilityRequestSuccessful); }
private void MediaEvent(uint eventType, int eventStatus) { if (eventStatus < 0) { this.mediaSession = null; // A session event reported an error if (this.EncodeError != null) { this.EncodeError(new COMException("Exception from HRESULT: 0x" + eventStatus.ToString("X", System.Globalization.NumberFormatInfo.InvariantInfo) + " (Media session event #" + eventType + ").", eventStatus)); } } else { switch (eventType) { case Consts.MESessionTopologySet: // Start playback from the start position MediaSessionStartPosition startPositionVar = new MediaSessionStartPosition((long)this.startPosition); this.mediaSession.Start(Guid.Empty, startPositionVar); break; case Consts.MESessionStarted: // Get the presentation clock IMFClock clock = null; this.mediaSession.GetClock(out clock); this.presentationClock = (IMFPresentationClock)clock; this.progressTimer.Start(); break; case Consts.MESessionEnded: // Close the media session. this.presentationClock = null; this.mediaSession.Close(); break; case Consts.MESessionStopped: // Close the media session. this.presentationClock = null; this.mediaSession.Close(); break; case Consts.MESessionClosed: // Stop the progress timer this.presentationClock = null; this.progressTimer.Stop(); // Shutdown the media source and session this.mediaSource.Shutdown(); this.mediaSession.Shutdown(); this.mediaSource = null; this.mediaSession = null; // Fire the EncodeCompleted event if (this.EncodeCompleted != null) { this.EncodeCompleted(this, null); } break; } } }
public static extern void MFCreateMediaSession(IntPtr pConfiguration, out IMFMediaSession ppMediaSession);
/// <summary> /// Starts the asychronous encode operation /// </summary> /// <param name="inputURL">Source filename</param> /// <param name="outputURL">Targe filename</param> /// <param name="audioOutput">Audio format that will be used for audio streams</param> /// <param name="videoOutput">Video format that will be used for video streams</param> /// <param name="startPosition">Starting position of the contet</param> /// <param name="endPosition">Position where the new content will end</param> public void Encode(string inputURL, string outputURL, AudioFormat audioOutput, VideoFormat videoOutput, ulong startPosition, ulong endPosition) { // If busy with other operation ignore and return if (this.IsBusy()) { return; } try { this.presentationClock = null; this.startPosition = startPosition; this.endPosition = endPosition; object objectSource = null; // Create the media source using source resolver and the input URL uint objectType = default(uint); this.mediaSource = null; // Init source resolver IMFSourceResolver sourceResolver = null; MFHelper.MFCreateSourceResolver(out sourceResolver); sourceResolver.CreateObjectFromURL(inputURL, Consts.MF_RESOLUTION_MEDIASOURCE, null, out objectType, out objectSource); this.mediaSource = (IMFMediaSource)objectSource; // Create the media session using a global start time so MF_TOPOLOGY_PROJECTSTOP can be used to stop the session this.mediaSession = null; IMFAttributes mediaSessionAttributes = null; MFHelper.MFCreateAttributes(out mediaSessionAttributes, 1); mediaSessionAttributes.SetUINT32(new Guid(Consts.MF_SESSION_GLOBAL_TIME), 1); MFHelper.MFCreateMediaSession(mediaSessionAttributes, out this.mediaSession); // Create the event handler AsyncEventHandler mediaEventHandler = new AsyncEventHandler(this.mediaSession); mediaEventHandler.MediaEvent += this.MediaEvent; // Get the stream descriptor IMFPresentationDescriptor presentationDescriptor = null; mediaSource.CreatePresentationDescriptor(out presentationDescriptor); // Get the duration presentationDescriptor.GetUINT64(new Guid(Consts.MF_PD_DURATION), out this.duration); IMFTranscodeProfile transcodeProfile = null; Guid containerType = new Guid(Consts.MFTranscodeContainerType_MPEG4); if (outputURL.EndsWith(".wmv", StringComparison.OrdinalIgnoreCase) || outputURL.EndsWith(".wma", StringComparison.OrdinalIgnoreCase)) { containerType = new Guid(Consts.MFTranscodeContainerType_ASF); } // Generate the transcoding profile transcodeProfile = SimpleFastEncode.CreateProfile(audioOutput, videoOutput, containerType); // Create the MF topology using the profile IMFTopology topology = null; MFHelper.MFCreateTranscodeTopology(this.mediaSource, outputURL, transcodeProfile, out topology); // Set the end position topology.SetUINT64(new Guid(Consts.MF_TOPOLOGY_PROJECTSTART), 0); topology.SetUINT64(new Guid(Consts.MF_TOPOLOGY_PROJECTSTOP), (endPosition == 0) ? this.duration : endPosition); // Set the session topology this.mediaSession.SetTopology((uint)Enums.MFSESSION_SETTOPOLOGY_FLAGS.None, topology); } catch (Exception ex) { this.mediaSession = null; // Fire the EncodeError event if (this.EncodeError != null) { this.EncodeError(new Exception(ex.Message, ex)); } } }
public AsyncEventHandler(IMFMediaSession mediaSession) { // Strart getting session events this.mediaSession = mediaSession; this.mediaSession.BeginGetEvent(this, null); }
private static extern int ExternMFCreateMediaSession( [In, MarshalAs(UnmanagedType.Interface)] IMFAttributes pConfiguration, [Out, MarshalAs(UnmanagedType.Interface)] out IMFMediaSession ppMS);
protected void CloseSession() { if (m_pVideoDisplay != null) { Marshal.ReleaseComObject(m_pVideoDisplay); m_pVideoDisplay = null; } if (m_pSession != null) { m_pSession.Close(); // Wait for the close operation to complete bool res = m_hCloseEvent.WaitOne(5000, true); if (!res) { TRACE(("WaitForSingleObject timed out!")); } } // Complete shutdown operations // 1. Shut down the media source if (m_pSource != null) { m_pSource.Shutdown(); SafeRelease(m_pSource); m_pSource = null; } // 2. Shut down the media session. (Synchronous operation, no events.) if (m_pSession != null) { m_pSession.Shutdown(); Marshal.ReleaseComObject(m_pSession); m_pSession = null; } }
/// <summary> /// Starts the Media Session. /// </summary> /// <param name="mediaSession">A valid IMFMediaSession instance.</param> /// <returns>If this function succeeds, it returns the S_OK member. Otherwise, it returns another HResult's member that describe the error.</returns> /// <remarks>This method starts the media session at its beginning.</remarks> public static HResult Start(this IMFMediaSession mediaSession) { return(Start(mediaSession, TimeSpan.FromTicks(0))); }
public static void MFCreateMediaSession(IMFAttributes configuration, out IMFMediaSession mediaSession) { int result = ExternMFCreateMediaSession(configuration, out mediaSession); if (result < 0) { throw new COMException("Exception from HRESULT: 0x" + result.ToString("X", System.Globalization.NumberFormatInfo.InvariantInfo) + " (MFCreateMediaSession)", result); } }
/// <summary> /// Init /// </summary> /// <param name="hVideo"></param> /// <param name="hEvent"></param> public Media(IntPtr hVideo, IntPtr hEvent) { TRACE("Media::Media"); Debug.Assert(hVideo != IntPtr.Zero); Debug.Assert(hEvent != IntPtr.Zero); m_pSession = null; m_pSource = null; m_pVideoDisplay = null; m_hwndVideo = hVideo; m_hwndEvent = hEvent; m_state = MediaState.Ready; m_hCloseEvent = new AutoResetEvent(false); MFExtern.MFStartup(MF_VERSION, MFStartup.Full); }
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> /// Constructor /// </summary> /// <param name="mediaSession">the media session. If not null, we will /// populate this object from the session</param> /// <history> /// 01 Nov 18 Cynic - Started /// </history> public TantaMediaSessionPlaybackRateCapabilities(IMFMediaSession mediaSession) { // get the playback capabilities AcquirePlayBackRates(mediaSession); }