MediaPlayerState.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Core / CSharp / System / Windows / Media / MediaPlayerState.cs / 1 / MediaPlayerState.cs

                            //------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation, 2003
//
//  File:       MediaPlayerState.cs 
//
//----------------------------------------------------------------------------- 
using System; 
using System.Threading;
using System.Security; 
using System.Security.Permissions;
using System.Diagnostics;
using System.ComponentModel;
using MS.Internal; 
using MS.Internal.PresentationCore;                        // SecurityHelper
using MS.Win32; 
using System.IO.Packaging; 
using System.Windows.Media.Animation;
using System.Windows.Media; 
using System.Windows.Media.Composition;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using System.Windows.Navigation; 
using System.Runtime.InteropServices;
using System.IO; 
using System.Security.AccessControl;//for semaphore access permissions 
using System.Net;
using Microsoft.Win32; 
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID;
using UnsafeNativeMethods=MS.Win32.PresentationCore.UnsafeNativeMethods;
 
//
// Disable the warnings that C# emmits when it finds pragmas it does not recognize, this is to 
// get rid of false positive PreSharp warning 
//
#pragma warning disable 1634, 1691 


namespace System.Windows.Media
{ 
    #region MediaPlayerState
 
    ///  
    /// MediaPlayerState
    /// Holds all of the local state that is required for playing media. This is 
    /// separated out into a separate class because MediaPlayer needs to be
    /// Animatable, but then that means it needs to be Freezable. However, media
    /// state cannot really be frozan (media piplines progress according to time
    /// and are very expensive), so instead, we make the "Frozen" object copy the 
    /// state object around. Doing this will also help in the remote case where
    /// we need to handle MediaPlayer quite differently on the channel in the 
    /// remote and local cases. 
    /// 
    internal class MediaPlayerState 
    {
        #region Constructors and Finalizers

        ///  
        /// Constructor
        ///  
        ///  
        /// SecurityCritical: This code sets a critical data member (_captureRenderTargetBitmap).
        /// SecurityTreatAsSafe: The critical member is set to a safe value (null). 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal
        MediaPlayerState( 
            MediaPlayer     mediaPlayer
            ) 
        { 
            _dispatcher = mediaPlayer.Dispatcher;
 
            _bitmapSource = null;

            _bitmapSourceDuceHandle = new DUCE.MultiChannelResource();
 
            _captureChannel = null;
 
            _captureRenderTargetBitmap = null; 

            _mediaContext = null; 

            _renderTargetRoot = DUCE.Resource.Null;

            Init(); 

            CreateMedia(mediaPlayer); 
 
            //
            // We need to know about new frames when they are sent so that we can 
            // capture the image data in the synchronous case.
            //
            _mediaEventsHelper.NewFrame += new EventHandler(OnNewFrame);
 
            //
            // Opened is actually fired when the media is prerolled. 
            // 
            _mediaEventsHelper.MediaPrerolled += new EventHandler(OnMediaOpened);
        } 

        //

        ///  
        /// Initialize local variables to their default state. After a close we want to restore this too, same as
        /// after construction. 
        ///  
        private
        void 
        Init()
        {
            _volume = DEFAULT_VOLUME;
            _balance = DEFAULT_BALANCE; 
            _speedRatio = 1.0;
            _paused = false; 
            _muted = false; 
            _sourceUri = null;
            _scrubbingEnabled = false; 
            _isRemote = false;

            //
            // Need to clear our bitmap source. 
            //
            ClearBitmapSource(); 
 
            //
            // Need to close our synchronous render infrastructure. 
            //
            CloseCaptureResources();
        }
 
        #endregion
 
        #region Public Methods 

        ///  
        /// Internal IsBuffering
        /// 
        /// 
        ///     Critical: This calls into unmanaged code and also acceses _nativemedia 
        ///     TreatAsSafe: This information about whether buffering is on is safe to expose
        ///  
        internal bool IsBuffering 
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            {
                VerifyAPI();
                bool isBuffering = false; 
                HRESULT.Check(MILMedia.IsBuffering(_nativeMedia, ref isBuffering));
                return isBuffering; 
            } 
        }
 
        /// 
        /// Internal CanPause
        /// 
        ///  
        ///     Critical: This is critical because it acceses _nativemedia and calls into unmanaged code
        ///     TreatAsSafe: This is safe to expose since giving out information about 
        ///     whether media can be paused is safe 
        /// 
        internal bool CanPause 
        {
            [SecurityCritical, SecurityTreatAsSafe]
            get
            { 
                VerifyAPI();
                bool canPause = false; 
                HRESULT.Check(MILMedia.CanPause(_nativeMedia, ref canPause)); 
                return canPause;
            } 
        }

        /// 
        /// Internal DownloadProgress 
        /// 
        ///  
        ///     Critical: This is critical it calls into unmanged code and accesses _nativeMedia 
        ///     TreatAsSafe: This is safe because the critical resource is not exposed and
        ///     returning download progress is safe 
        /// 
        internal double DownloadProgress
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            { 
                VerifyAPI(); 
                double downloadProgress = 0;
                HRESULT.Check(MILMedia.GetDownloadProgress(_nativeMedia, ref downloadProgress)); 
                return downloadProgress;
            }
        }
 
        /// 
        /// Internal BufferingProgress 
        ///  
        /// 
        ///     Critical: This is critical it calls into unmanged code and accesses _nativeMedia 
        ///     TreatAsSafe: This is safe because the critical resource is not exposed and
        ///     returning buffering progress is safe
        /// 
        internal double BufferingProgress 
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get 
            {
                VerifyAPI(); 
                double bufferingProgress = 0;
                HRESULT.Check(MILMedia.GetBufferingProgress(_nativeMedia, ref bufferingProgress));
                return bufferingProgress;
            } 
        }
 
        ///  
        /// Returns the Height
        ///  
        /// 
        ///     Critical: This is critical it calls into unmanged code and accesses _nativeMedia
        ///     TreatAsSafe: This is safe because the critical resource is not exposed and
        ///     returning natural video height is safe 
        /// 
        internal Int32 NaturalVideoHeight 
        { 
            [SecurityCritical, SecurityTreatAsSafe]
            get 
            {
                VerifyAPI();

                UInt32 height = 0; 

                HRESULT.Check(MILMedia.GetNaturalHeight(_nativeMedia, ref height)); 
                return (Int32)height; 
            }
        } 

        /// 
        /// Returns the Width
        ///  
        /// 
        ///     Critical: This is critical it calls into unmanged code and accesses _nativeMedia 
        ///     TreatAsSafe: This is safe because the critical resource is not exposed and 
        ///     returning natural video width is safe
        ///  
        internal Int32 NaturalVideoWidth
        {
            [SecurityCritical, SecurityTreatAsSafe]
            get 
            {
                VerifyAPI(); 
 
                UInt32 width = 0;
 
                HRESULT.Check(MILMedia.GetNaturalWidth(_nativeMedia, ref width));
                return (Int32)width;
            }
        } 

        ///  
        /// If media has audio content 
        /// 
        ///  
        ///     Critical: This is critical it calls into unmanged code and accesses _nativeMedia
        ///     TreatAsSafe: This is safe because the critical resource is not exposed and
        ///     returning whether media has audio is safe
        ///  
        internal bool HasAudio
        { 
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            { 
                VerifyAPI();

                bool hasAudio = true;
 
                HRESULT.Check(MILMedia.HasAudio(_nativeMedia, ref hasAudio));
                return hasAudio; 
            } 
        }
 
        /// 
        /// If the media has video content
        /// 
        ///  
        ///     Critical: This is critical it calls into unmanged code and accesses _nativeMedia
        ///     TreatAsSafe: This is safe because the critical resource is not exposed and 
        ///     returning whether media has video is safe 
        /// 
        internal bool HasVideo 
        {
            [SecurityCritical, SecurityTreatAsSafe]
            get
            { 
                VerifyAPI();
 
                bool hasVideo = false; 

                HRESULT.Check(MILMedia.HasVideo(_nativeMedia, ref hasVideo)); 
                return hasVideo;
            }
        }
 
        /// 
        /// Location of the media to play. Open opens the media, this property 
        /// allows the source that is currently playing to be retrieved. 
        /// 
        internal Uri Source 
        {
            get
            {
                VerifyAPI(); 

                return _sourceUri; 
            } 
        }
 
        /// 
        /// Internal Get Volume
        /// 
        ///  
        ///     Critical: This is critical because it calls into unmanged code and accesses _nativeMedia
        ///     TreatAsSafe: This is safe because the critical resource is not exposed and 
        ///     returning volume ratio is safe and so also is setting it 
        /// 
        internal double Volume 
        {
            [SecurityCritical, SecurityTreatAsSafe]
            get
            { 

                VerifyAPI(); 
 
                return _volume;
            } 
            [SecurityCritical, SecurityTreatAsSafe]
            set
            {
                VerifyAPI(); 
                if (Double.IsNaN(value))
                { 
                    throw new ArgumentException(SR.Get(SRID.ParameterValueCannotBeNaN), "value"); 
                }
 
                if (DoubleUtil.GreaterThanOrClose(value, 1))
                {
                    value = 1;
                } 
                else if (DoubleUtil.LessThanOrClose(value, 0))
                { 
                    value = 0; 
                }
 
                // We only want to set the volume if the current cached volume is not the same
                // No need to do extra work.
                if (!DoubleUtil.AreClose(_volume, value))
                { 
                    if (!_muted)
                    { 
                        int hr = MILMedia.SetVolume(_nativeMedia, value); 

                        HRESULT.Check(hr); 

                        // value is changing
                        _volume = value;
                    } 
                    else
                    { 
                        // If we are muted, cache the volume 
                        _volume = value;
                    } 
                }
            }
        }
 
        /// 
        /// Internal Get Balance 
        ///  
        /// 
        ///     Critical: This is accesses the native media. 
        ///     TreatAsSafe: This is safe because the act of adjusting the balance is a safe one.
        /// 
        internal double Balance
        { 
            [SecurityCritical, SecurityTreatAsSafe]
            get 
            { 

                VerifyAPI(); 

                return _balance;
            }
            [SecurityCritical, SecurityTreatAsSafe] 
            set
            { 
                VerifyAPI(); 
                if (Double.IsNaN(value))
                { 
                    throw new ArgumentException(SR.Get(SRID.ParameterValueCannotBeNaN), "value");
                }

                if (DoubleUtil.GreaterThanOrClose(value, 1)) 
                {
                    value = 1; 
                } 
                else if (DoubleUtil.LessThanOrClose(value, -1))
                { 
                    value = -1;
                }

                // We only want to set the balance if the current cached balance 
                // is not the same. No need to do extra work.
                if (!DoubleUtil.AreClose(_balance, value)) 
                { 
                    int hr = MILMedia.SetBalance(_nativeMedia, value);
 
                    HRESULT.Check(hr);

                    // value is changing
                    _balance = value; 
                }
            } 
        } 

        ///  
        /// Whether or not scrubbing is enabled
        /// 
        /// 
        ///     Critical: This accesses the native media. 
        ///     TreatAsSafe: This is safe because it's safe to adjust whether or not scrubbing is enabled
        ///  
        internal bool ScrubbingEnabled 
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            {
                VerifyAPI();
                return _scrubbingEnabled; 
            }
            [SecurityCritical, SecurityTreatAsSafe] 
            set 
            {
                VerifyAPI(); 
                if (value != _scrubbingEnabled)
                {
                    HRESULT.Check(MILMedia.SetIsScrubbingEnabled(_nativeMedia, value));
                    _scrubbingEnabled = value; 
                }
            } 
        } 

        ///  
        /// Internal Get Mute
        /// 
        internal bool IsMuted
        { 
            get
            { 
                VerifyAPI(); 
                return _muted;
            } 
            set
            {
                VerifyAPI();
 
                // we need to store the volume since this.Volume will change the cached value
                double volume = _volume; 
 
                if (value && !_muted)
                { 
                    // Going from Unmuted -> Muted

                    // Set the volume to 0
                    this.Volume = 0; 
                    _muted = true;
 
                    // make sure cached volume is previous value 
                    _volume = volume;
                } 
                else if (!value && _muted)
                {
                    // Going from Muted -> Unmuted
 
                    _muted = false;
 
                    // set cached volume to 0 since this. Volume will only change volume 
                    // if cached volume and new volume differ
                    _volume = 0; 

                    // set volume to old cached value, which will also update our current cached value
                    this.Volume = volume;
                } 
            }
        } 
 
        /// 
        ///     Critical: This is critical it calls into unmanged code and accesses _nativeMedia 
        ///     TreatAsSafe: This is safe because the critical resource is not exposed and
        ///     returning natural duration is safe
        /// 
        internal Duration NaturalDuration 
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get 
            {
                VerifyAPI(); 

                long mediaLength = 0;
                HRESULT.Check(MILMedia.GetMediaLength(_nativeMedia, ref mediaLength));
                if (mediaLength == 0) 
                {
                    return Duration.Automatic; 
                } 
                else
                { 
                    return new Duration(TimeSpan.FromTicks(mediaLength));
                }
            }
        } 

        ///  
        /// Seek to specified position 
        /// 
        internal TimeSpan Position 
        {
            set
            {
                VerifyAPI(); 

                VerifyNotControlledByClock(); 
 
                SetPosition(value);
            } 
            get
            {
                VerifyAPI();
 
                return GetPosition();
            } 
        } 

        ///  
        /// The current speed. This cannot be changed if a clock is controlling this player
        /// 
        internal double SpeedRatio
        { 
            get
            { 
                VerifyAPI(); 

                return _speedRatio; 
            }
            set
            {
                VerifyAPI(); 
                VerifyNotControlledByClock();
 
                if (value < 0) 
                {
                    value = 0; // we clamp negative values to 0 
                }

                SetSpeedRatio(value);
            } 
        }
 
        ///  
        /// The dispatcher, this is actually derived from the media player
        /// on construction. 
        /// 
        internal Dispatcher Dispatcher
        {
            get 
            {
                return _dispatcher; 
            } 
        }
 

        #endregion

        #region EventHandlers 

        ///  
        /// Raised when there is an error opening or playing media 
        /// 
        internal event EventHandler MediaFailed 
        {
            add
            {
                VerifyAPI(); 
                _mediaEventsHelper.MediaFailed += value;
            } 
            remove 
            {
                VerifyAPI(); 
                _mediaEventsHelper.MediaFailed -= value;
            }
        }
 
        /// 
        /// Raised when the media has been opened. 
        ///  
        internal event EventHandler MediaOpened
        { 
            add
            {
                VerifyAPI();
 
                _mediaOpenedHelper.AddEvent(value);
            } 
            remove 
            {
                VerifyAPI(); 

                _mediaOpenedHelper.RemoveEvent(value);
            }
        } 

 
        ///  
        /// Raised when the media has finished.
        ///  
        internal event EventHandler MediaEnded
        {
            add
            { 
                VerifyAPI();
                _mediaEventsHelper.MediaEnded += value; 
            } 
            remove
            { 
                VerifyAPI();
                _mediaEventsHelper.MediaEnded -= value;
            }
        } 

 
        ///  
        /// Raised when media begins buffering.
        ///  
        internal event EventHandler BufferingStarted
        {
            add
            { 
                VerifyAPI();
                _mediaEventsHelper.BufferingStarted += value; 
            } 
            remove
            { 
                VerifyAPI();
                _mediaEventsHelper.BufferingStarted -= value;
            }
        } 

 
        ///  
        /// Raised when media finishes buffering.
        ///  
        internal event EventHandler BufferingEnded
        {
            add
            { 
                VerifyAPI();
 
                _mediaEventsHelper.BufferingEnded += value; 
            }
            remove 
            {
                VerifyAPI();

                _mediaEventsHelper.BufferingEnded -= value; 
            }
        } 
 
        /// 
        /// Raised when a script command embedded in the media is encountered. 
        /// 
        internal event EventHandler ScriptCommand
        {
            add 
            {
                VerifyAPI(); 
                _mediaEventsHelper.ScriptCommand += value; 
            }
            remove 
            {
                VerifyAPI();
                _mediaEventsHelper.ScriptCommand -= value;
            } 
        }
 
        ///  
        /// Raised when a new frame in the media is encountered, we only
        /// send one new frame per AddRefOnChannel in synchronous mode only. 
        /// 
        internal event EventHandler NewFrame
        {
            add 
            {
                VerifyAPI(); 
 
                _newFrameHelper.AddEvent(value);
            } 

            remove
            {
                VerifyAPI(); 

                _newFrameHelper.RemoveEvent(value); 
            } 
        }
 
        #endregion

        #region Clock dependent properties and methods
 
        /// 
        /// The clock driving this instance of media 
        ///  
        internal MediaClock Clock
        { 
            get
            {
                VerifyAPI();
                return _mediaClock; 
            }
        } 
 
        internal
        void 
        SetClock(
            MediaClock  clock,
            MediaPlayer player
            ) 
        {
            VerifyAPI(); 
            MediaClock oldClock = _mediaClock; 
            MediaClock newClock = clock;
 
            // Avoid infinite loops
            if (oldClock != newClock)
            {
                _mediaClock = newClock; 

                // Disassociate the old clock 
                if (oldClock != null) 
                {
                    oldClock.Player = null; 
                }

                // Associate the new clock;
                if (newClock != null) 
                {
                    newClock.Player = player; 
                } 

                // According to the spec, setting the Clock to null 
                // should set the Source to null
                if (newClock == null)
                {
                    Open(null); 
                }
            } 
        } 

        ///  
        /// Open the media, at this point the underlying native resources are
        /// created. The media player cannot be controlled when it isn't opened.
        /// 
        internal 
        void
        Open( 
            Uri      source 
            )
        { 
            VerifyAPI();
            VerifyNotControlledByClock();

            SetSource(source); 

            // Workaround for bug 107397: Resuing one instance of MediaElement and 
            // calling play() wont result in seek to zero, Media Freezes.  Ensure 
            // we set Media to play from the beginning.
            SetPosition(TimeSpan.Zero); 
        }

        /// 
        /// Begin playback. This operation is not allowed if a clock is 
        /// controlling this player
        ///  
        internal void Play() 
        {
            VerifyAPI(); 
            VerifyNotControlledByClock();

            _paused = false;
            PrivateSpeedRatio = SpeedRatio; 
        }
 
        ///  
        /// Halt playback at current position. This operation is not allowed if
        /// a clock is controlling this player 
        /// 
        internal void Pause()
        {
            VerifyAPI(); 
            VerifyNotControlledByClock();
 
            _paused = true; 
            PrivateSpeedRatio = 0;
        } 

        /// 
        /// Halt playback and seek to the beginning of media. This operation is
        /// not allowed if a clock is controlling this player 
        /// 
        internal void Stop() 
        { 
            VerifyAPI();
            VerifyNotControlledByClock(); 

            Pause();
            Position = TimeSpan.FromTicks(0);
        } 

        ///  
        /// Closes the underlying media. This de-allocates all of the native resources in 
        /// the media. The mediaplayer can be opened again by calling the Open method.
        ///  
        /// 
        ///     Critical: This calls into unmanaged code and also acceses _nativemedia.
        ///     TreatAsSafe: Intrinsically safe to close media.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal 
        void 
        Close()
        { 
            VerifyAPI();

            VerifyNotControlledByClock();
 
            HRESULT.Check(MILMedia.Close(_nativeMedia));
 
            // 
            // Once we successfully close, we don't have a clock anymore.
            // Assign the property so that the clock is disconnected from the 
            // player as well as the player from the clock.
            //
            SetClock(null, null);
 
            Init();
        } 
 
        /// 
        /// Sends a command to play the given media. 
        /// 
        /// 
        ///     Critical: This calls into unmanaged code and also acceses _nativemedia.
        ///     TreatAsSafe: Media Command merely binds resource to native player. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal 
        void
        SendCommandMedia( 
            DUCE.Channel            channel,
            DUCE.ResourceHandle     handle,
            bool                    notifyUceDirectly,
            bool                    isRemote 
            )
        { 
            _isRemote = isRemote; 

            // 
            // If this is remote, then we want to marshal over the
            // bitmap source we captured from the media (if it
            // is available).
            // 
            if (isRemote)
            { 
                // 
                // If we have a bitmap source and the bitmap source handle
                // isn't on this channel, then create it. 
                //
                if (_bitmapSource != null)
                {
                    // 
                    // If we have a bitmap source and we haven't created
                    // the the _duceHandle, then create it now. 
                    // 
                    if (!_bitmapSourceDuceHandle.IsOnChannel(channel))
                    { 
                        //
                        // Create the bitap source duce handle.
                        //
                        _bitmapSourceDuceHandle.CreateOrAddRefOnChannel(channel, DUCE.ResourceType.TYPE_BITMAPSOURCE); 
                    }
 
                    // 
                    // Send the bitmap source down the channel.
                    // 
                    channel.SendCommandBitmapSource(
                                _bitmapSourceDuceHandle.GetHandle(channel),
                                _bitmapSource,
                                true,       // share the bitmap 
                                true);      // system memory bitmap.
                } 
            } 
            else
            { 
                //
                // If we are actually moved onto a local channel, we don't
                // wan't our bitmap source lieing around.
                // 
                ClearBitmapSource();
 
                // 
                // Make sure that the capture resources are closed.
                // 
                CloseCaptureResources();
            }

            SendMediaPlayerCommand( 
                channel,
                handle, 
                notifyUceDirectly, 
                isRemote);
 

            //
            // Independently, tell the native media that we need to update the UI, the
            // reason we do this directly through the player is that effects can immediately 
            // remove the channel on us and hence media might not get a chance to see
            // the media player resource. 
            // 
            if (!notifyUceDirectly)
            { 
                NeedUIFrameUpdate();

                //
                // We need to force a present on each pass otherwise we won't get any 
                // frame updates.
                // 
                // 
                // If this is remote, we want to start capturing the frame if we have
                // been opened already. 
                //
                if (isRemote && HasNonEmptyVideo)
                {
                    OpenCaptureResources(); 

                    _captureChannel.Present(); 
 
                    _mediaContext.NotifySyncChannelMessage(_captureChannel);
                } 
            }
        }

        private 
        bool
        HasNonEmptyVideo 
        { 
            get
            { 
                return NaturalVideoWidth != 0 && NaturalVideoHeight != 0;
            }
        }
 
        /// 
        /// Sends a request to the media player to reserve a UI frame for notification. 
        ///  
        /// 
        ///     Critical: This calls into unmanaged code and also acceses _nativemedia. 
        ///     TreatAsSafe: Asking for a frame update is inherently safe.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private 
        void
        NeedUIFrameUpdate() 
        { 
            VerifyAPI();
 
            HRESULT.Check(MILMedia.NeedUIFrameUpdate(_nativeMedia));
        }

 
        /// 
        /// Sends a command to play the given media. 
        ///  
        /// 
        ///     Critical: This calls into unmanaged code and also acceses _nativemedia. 
        ///     TreatAsSafe: Media Command merely binds resource to native player.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal 
        void
        ReleaseOnChannel( 
            DUCE.Channel            channel 
            )
        { 
            //
            // If the bitmap source handle is on this channel, then release it.
            //
            if (_bitmapSourceDuceHandle.IsOnChannel(channel)) 
            {
                _bitmapSourceDuceHandle.ReleaseOnChannel(channel); 
            } 

            // 
            // Remove the capture resources.
            //
            CloseCaptureResources();
        } 

        #endregion 
 
        #region Private Methods
 
        /// 
        /// Create the unmanaged media resources
        /// 
        ///  
        /// Critical - calls unmanaged code, access pointer parameters. It instantiates
        ///            windows media player 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private void CreateMedia(MediaPlayer mediaPlayer) 
        {
            CheckMediaDisabledFlags();

            SafeMILHandle unmanagedProxy = null; 
            MediaEventsHelper.CreateMediaEventsHelper(mediaPlayer, out _mediaEventsHelper, out unmanagedProxy);
            try 
            { 
                using (FactoryMaker myFactory = new FactoryMaker())
                { 
                    HRESULT.Check(UnsafeNativeMethods.MILFactory2.CreateMediaPlayer(
                            myFactory.FactoryPtr,
                            unmanagedProxy,
                            SecurityHelper.CallerHasMediaPermission(MediaPermissionAudio.AllAudio, MediaPermissionVideo.AllVideo, MediaPermissionImage.NoImage), 
                            MediaSystem.DeviceId,
                            out _nativeMedia 
                            )); 
                }
            } 
            catch
            {
                if (_nativeMedia != null && !_nativeMedia.IsInvalid)
                { 
                    _nativeMedia.Close();
                } 
 
                throw;
            } 

            Helper helper = new Helper(_nativeMedia);
            AppDomain.CurrentDomain.ProcessExit += helper.ProcessExitHandler;
        } 

        ///  
        /// Open Media 
        /// 
        ///  
        /// Critical - access critical resource (_nativeMedia), access local file system
        /// and also stores the path to base directory in a local variable. It also asserts
        /// to allow FileIO to local directory. It calls GetBaseDirectory, that returns sensitive information.
        /// TreatAsSafe: This path is sent to the unmanaged layer to be opened. Also it demands 
        /// fileio for absolute paths and web permissions for files on a server. It only lets you access
        /// files in current directory and does not expose the location of current directory 
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        private void OpenMedia(Uri source) 
        {
            string toOpen = null;

            if (source != null && source.IsAbsoluteUri && source.Scheme == PackUriHelper.UriSchemePack) 
            {
                try 
                { 
                    source = BaseUriHelper.ConvertPackUriToAbsoluteExternallyVisibleUri(source);
                } 
                catch (InvalidOperationException)
                {
                    source = null;
                    _mediaEventsHelper.RaiseMediaFailed(new System.NotSupportedException(SR.Get(SRID.Media_PackURIsAreNotSupported, null))); 
                }
            } 
 
            // Setting a null source effectively disconects the MediaElement.
            if (source != null) 
            {
                // keep whether we asserted permissions or not
                bool elevated = false;
 
                // get the base directory of the application; never expose this
                Uri appBase = SecurityHelper.GetBaseDirectory(AppDomain.CurrentDomain); 
 
                // this extracts the URI to open
                Uri uriToOpen = ResolveUri(source, appBase); 

                // access is allowed in the following cases (only 1 & 2 require elevation):
                // 1) to any HTTPS media if app is NOT coming from HTTPS
                // 2) to URI in the current directory of the fusion cache 
                // 3) to site of origin media
                if (SecurityHelper.AreStringTypesEqual(uriToOpen.Scheme, Uri.UriSchemeHttps)) 
                { 
                    // target is HTTPS. Then, elevate ONLY if we are NOT coming from HTTPS (=XDomain HTTPS app to HTTPS media disallowed)
                    Uri appDeploymentUri = SecurityHelper.ExtractUriForClickOnceDeployedApp(); 
                    if (!SecurityHelper.AreStringTypesEqual(appDeploymentUri.Scheme, Uri.UriSchemeHttps))
                    {
                        new WebPermission(NetworkAccess.Connect, BindUriHelper.UriToString(uriToOpen)).Assert();
                        elevated = true; 
                    }
                } 
                else 
                {
                    // elevate to allow access to media in the app's directory in the fusion cache. 
                    new FileIOPermission(FileIOPermissionAccess.Read, appBase.LocalPath).Assert();// BlessedAssert
                    elevated = true;
                }
 
                // demand permissions. if demands succeds, it means we are in one of the cases above.
                try 
                { 
                    toOpen  = DemandPermissions(uriToOpen);
                } 
                finally
                {
                    if (elevated)
                    { 
                        CodeAccessPermission.RevertAssert();
                    } 
                } 
            }
            else 
            {
                toOpen = null;
            }
 
            // We pass in exact same URI for which we demanded permissions so that we can be sure
            // there is no discrepancy between the two. 
            HRESULT.Check(MILMedia.Open(_nativeMedia, toOpen)); 
        }
 
        /// 
        ///     Critical: This code elevates to read registry
        ///     TreatAsSafe: Detecting whether media is disabled is a safe operation
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        private void CheckMediaDisabledFlags() 
        { 
            if (SafeSecurityHelper.IsFeatureDisabled(SafeSecurityHelper.KeyToRead.MediaAudioOrVideoDisable))
            { 
                // in case the registry key is '1' then demand
                //Demand media permission here for Video or Audio
                // Issue: 1232606 need to fix once clr has the media permissions
                SecurityHelper.DemandMediaPermission(MediaPermissionAudio.AllAudio, 
                                                     MediaPermissionVideo.AllVideo,
                                                     MediaPermissionImage.NoImage); 
            } 
        }
 
        /// 
        ///     Critical: This code returns the base directory of the app as a URI
        ///     IT constructs a Uri based on relative and absolute URI
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private Uri ResolveUri(Uri uri, Uri appBase) 
        { 
            if (uri.IsAbsoluteUri)
            { 
                return uri;
            }
            else
            { 
                return new Uri(appBase, uri);
            } 
        } 

        // returns the exact string on which we demanded permissions 

        /// 
        ///     Critical: This code is used to safeguard against various forms of attacks
        ///     to restrict access to loose file passed as relative path in the application 
        ///     base direcory
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        private string DemandPermissions(Uri absoluteUri)
        { 
            Debug.Assert(absoluteUri.IsAbsoluteUri);
            string toOpen = BindUriHelper.UriToString(absoluteUri);
            int targetZone = SecurityHelper.MapUrlToZoneWrapper(absoluteUri);
 
            if (targetZone == NativeMethods.URLZONE_LOCAL_MACHINE)
            { 
                // go here only for files and not for UNC 
                if (absoluteUri.IsFile)
                { 
                    // Please note this pattern is unique and NEEDS TO EXIST , it prevents
                    // access to any folder but the one where the app is running from.
                    // PLEASE DO NOT REMOVE THIS DEMAND AND THE ASSERT IN THE CALLING CODE
                    toOpen = absoluteUri.LocalPath; 
                    (new FileIOPermission(FileIOPermissionAccess.Read, toOpen)).Demand();
                } 
            } 
            else //Any other zone
            { 
                // UNC path pointing to a file (We filter for `http://intranet)
                if (absoluteUri.IsFile && absoluteUri.IsUnc)
                {
                    // perform checks for UNC content 
                    SecurityHelper.EnforceUncContentAccessRules(absoluteUri);
 
                    // In this case we first check to see if the consumer has media permissions for 
                    // safe media (Site of Origin + Cross domain).
                    if (!SecurityHelper.CallerHasMediaPermission(MediaPermissionAudio.SafeAudio, 
                                                                 MediaPermissionVideo.SafeVideo,
                                                                 MediaPermissionImage.NoImage))
                    {
                        // if he does not then we demand web permission to allow access only to site of origin 
                        (new FileIOPermission(FileIOPermissionAccess.Read, toOpen)).Demand();
                    } 
 
                }
                else // Any other path 
                {
                    // In this case we first check to see if the consumer has media permissions for
                    // safe media (Site of Origin + Cross domain).
                    if (absoluteUri.Scheme != Uri.UriSchemeHttps) 
                    {
                        //accessing non https content from an https app is disallowed 
                        SecurityHelper.BlockCrossDomainForHttpsApps(absoluteUri); 
                        if (!SecurityHelper.CallerHasMediaPermission(MediaPermissionAudio.SafeAudio,
                                                                     MediaPermissionVideo.SafeVideo, 
                                                                     MediaPermissionImage.NoImage))
                        {
                            // if he does not then we demand web permission to allow access only to site of origin
                            (new WebPermission(NetworkAccess.Connect, toOpen)).Demand(); 
                        }
                    } 
                    else// This is the case where target content is HTTPS 
                    {
                        (new WebPermission(NetworkAccess.Connect, toOpen)).Demand(); 
                    }

                }
            } 

            return toOpen; 
        } 

        ///  
        /// Seek to specified position (in 100 nanosecond ticks)
        /// 
        /// 
        /// Critical - access critical resource (_nativeMedia) 
        /// TreatAsSafe - critical resource isn't modified or handed out
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        internal void SetPosition(TimeSpan value)
        { 
            VerifyAPI();

            HRESULT.Check(MILMedia.SetPosition(_nativeMedia, value.Ticks));
        } 

        ///  
        /// get the current position (in 100 nanosecond ticks) 
        /// 
        ///  
        /// Critical - access critical resource (_nativeMedia)
        /// TreatAsSafe - critical resource isn't modified or handed out
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private TimeSpan GetPosition()
        { 
            VerifyAPI(); 

            long position = 0; 
            HRESULT.Check(MILMedia.GetPosition(_nativeMedia, ref position));
            return TimeSpan.FromTicks(position);
        }
 
        /// 
        /// Critical - access critical resource (_nativeMedia) 
        /// TreatAsSafe - critical resource isn't modified or handed out 
        /// 
        private double PrivateSpeedRatio 
        {
            [SecurityCritical, SecurityTreatAsSafe]
            set
            { 
                VerifyAPI();
 
                if (Double.IsNaN(value)) 
                {
                    throw new ArgumentException(SR.Get(SRID.ParameterValueCannotBeNaN), "value"); 
                }

                HRESULT.Check(MILMedia.SetRate(_nativeMedia, value));
            } 
        }
 
        // 
        // Set the current speed.
        // 
        internal void SetSpeedRatio(double value)
        {
            _speedRatio = value;
 
            //
            // We don't change the speed if we are paused, unless we are in 
            // clock mode, which overrides paused mode. 
            //
            if (!_paused || _mediaClock != null) 
            {
                PrivateSpeedRatio = _speedRatio;
            }
        } 

        ///  
        /// Sets the source of the media (and opens it), without checking whether 
        /// we are under clock control. This is called by the clock.
        ///  
        internal
        void
        SetSource(
            Uri      source 
            )
        { 
            if (source != _sourceUri) 
            {
                OpenMedia(source); 

                //
                // Only assign the source uri if the OpenMedia succeeds.
                // 
                _sourceUri = source;
            } 
        } 

 
        /// 
        /// Verifies this object is in an accessible state, and that we
        /// are being called from the correct thread. This method should
        /// be the first thing called from any internal method. 
        /// 
        ///  
        /// Critical - access critical resource (_nativeMedia) 
        /// TreatAsSafe - critical resource isn't modified or handed out
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private void VerifyAPI()
        {
            // 
            // We create _nativeMedia in the constructor, so it should always
            // be initialized. 
            // 
            Debug.Assert(_nativeMedia != null && !_nativeMedia.IsInvalid);
 
            //
            // We only allow calls to any media object on the UI thread.
            //
            _dispatcher.VerifyAccess(); 

            if (_nativeMedia == null || _nativeMedia.IsInvalid) 
            { 
                throw new System.NotSupportedException(SR.Get(SRID.Image_BadVersion));
            } 
        }

        /// 
        /// Verifies that this player is not currently controlled by a clock. Some actions are 
        /// invalid while we are under clock control.
        ///  
        private 
        void
        VerifyNotControlledByClock() 
        {
            if (Clock != null)
            {
                throw new InvalidOperationException(SR.Get(SRID.Media_NotAllowedWhileTimingEngineInControl)); 
            }
        } 
 
        /// 
        /// Clears the bitmap source. 
        /// 
        /// 
        /// Critical - calls LinkDemand-protected SafeHandle.Close
        /// TreatAsSafe - doesn't accept an arbitrary handle to close 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private 
        void
        ClearBitmapSource() 
        {
            //
            // Close the bitmap source,
            // 
            if (_bitmapSource != null)
            { 
                _bitmapSource.Close(); 

                _bitmapSource = null; 
            }
        }

        ///  
        /// SendMediaPlayerCommand
        ///               SecurityNote 
        ///  
        /// Critical - access critical resource (_nativeMedia)
        /// TreatAsSafe - critical resource is treated like any other image. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private
        void 
        SendMediaPlayerCommand(
            DUCE.Channel            channel, 
            DUCE.ResourceHandle     handle, 
            bool                    notifyUceDirectly,
            bool                    isRemote 
            )
        {
//
// This is an interrop call, but, it does not set a last error being a COM call. So, suppress the 
// presharp warning about losing last error.
// 
#pragma warning disable 6523 

            // 
            // AddRef to ensure the media player stays alive during transport, even if the
            // MediaPlayer goes away.  The slave video resource takes ownership of this AddRef.
            // Note there is still a gray danger zone here -- if the channel command is lost
            // this reference won't be cleaned up. 
            //
            // 
 

 

            if (!isRemote)
            {
                UnsafeNativeMethods.MILUnknown.AddRef(_nativeMedia); 
            }
 
            channel.SendCommandMedia( 
                handle,
                _nativeMedia, 
                isRemote ? _bitmapSourceDuceHandle.GetHandle(channel) : DUCE.ResourceHandle.Null,
                notifyUceDirectly,
                isRemote);
 
#pragma warning restore 6523
        } 
 
        /// 
        /// Close all of the capture resources. 
        /// 
        /// 
        /// SecurityCritical: This code references critical data (_captureRenderTargetBitmap).
        /// SecurityTreatAsSafe: It just checks for a null value. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private 
        void
        CloseCaptureResources() 
        {
            //
            // We don't clear our bitmap source because this can result on us
            // getting a channel change without a bitmap source. This is bad. 
            //
            if (null != _captureRenderTargetBitmap) 
            { 
                CloseRenderTarget();
            } 

            if (null != _captureChannel)
            {
                CloseSyncChannel(); 
            }
        } 
 
        /// 
        /// Open all of the capture resources we need 
        /// 
        /// 
        /// SecurityCritical: This code references critical data (_captureRenderTargetBitmap).
        /// SecurityTreatAsSafe: It just checks for a null value. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private 
        void
        OpenCaptureResources() 
        {
            if (null == _captureChannel)
            {
                OpenSyncChannel(); 
            }
 
            if (null == _captureRenderTargetBitmap) 
            {
                OpenRenderTarget(); 
            }
        }

        ///  
        /// Open the synchronous channel.
        ///  
        private 
        void
        OpenSyncChannel() 
        {
            _mediaContext = MediaContext.CurrentMediaContext;

            // 
            // Allocate a synchronous channel to receive the result from
            // the media player. 
            // 
            _captureChannel = _mediaContext.AllocateSyncChannel();
        } 

        /// 
        /// Close the synchronous channel.
        ///  
        private
        void 
        CloseSyncChannel() 
        {
            _mediaContext.ReleaseSyncChannel(_captureChannel); 

            _mediaContext = null;

            _captureChannel = null; 
        }
 
        ///  
        /// Close the render target
        ///  
        /// 
        /// Critical - calls LinkDemand-protected SafeHandle.Close.  Accesses _captureRenderTargetBitmap.
        /// TreatAsSafe - doesn't accept an arbitrary handle to close.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private 
        void 
        CloseRenderTarget()
        { 
            _captureRenderTargetBitmap.Close();

            _captureRenderTargetBitmap = null;
 
            if (!_renderTargetRoot.Handle.IsNull)
            { 
                DUCE.CompositionNode.RemoveAllChildren(_renderTargetRoot.Handle, _captureChannel); 

                _renderTargetRoot.ReleaseOnChannel(_captureChannel); 
            }
        }

        ///  
        /// Captures the frame from the native media by creating a synchrous channel
        /// with a RTBitmap and acquiring the image source. 
        ///  
        /// 
        /// Critical - access critical resource (_nativeMedia, renderTargetBitmap, _captureRenderTargetBitmap). 
        /// TreatAsSafe - critical resource is treated like any other image (e.g. DrawImage code):
        /// We are sending images because we need to send them across the wire if we are drawing video remotely.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private
        void 
        OpenRenderTarget() 
        {
            uint width = (uint)NaturalVideoWidth; 
            uint height = (uint)NaturalVideoHeight;

            Debug.Assert(width != 0 && height != 0);
 
            using(FactoryMaker myFactory = new FactoryMaker())
            { 
                HRESULT.Check( 
                    UnsafeNativeMethods.MILFactory2.CreateBitmapRenderTarget(
                        myFactory.FactoryPtr, 
                        width,
                        height,
                        PixelFormatEnum.Pbgra32,
                        _defaultDevicePixelsPerInch, 
                        _defaultDevicePixelsPerInch,
                        MILRTInitializationFlags.MIL_RT_INITIALIZE_DEFAULT, 
                        out _captureRenderTargetBitmap)); 

                IntPtr  pIRenderTargetBitmap = IntPtr.Zero; 

                Guid iidRenterTargetBitmap = MILGuidData.IID_IMILRenderTargetBitmap;

                try 
                {
                    // 
                    // We need the render target bitmap. 
                    //
                    HRESULT.Check( 
                        UnsafeNativeMethods.MILUnknown.QueryInterface(
                            _captureRenderTargetBitmap,
                            ref iidRenterTargetBitmap,
                            out pIRenderTargetBitmap)); 

                    // 
                    // Render the frame. 
                    //
                    RenderFrame(pIRenderTargetBitmap, width, height); 
                }
                finally
                {
                    UnsafeNativeMethods.MILUnknown.ReleaseInterface(ref pIRenderTargetBitmap); 
                }
            } 
        } 

 
        /// 
        /// Renders the frame
        /// 
        ///  
        /// Critical - access critical resource (_nativeMedia and renderTargetBitmap)
        ///  
        [SecurityCritical] 
        private
        void 
        RenderFrame(
            IntPtr              pIRenderTargetBitmap,
            uint                width,
            uint                height 
            )
        { 
            DUCE.Resource target = new DUCE.Resource(); 

            DUCE.Resource mediaPlayer = new DUCE.Resource(); 

            DUCE.Resource renderData = new DUCE.Resource();

            DUCE.Resource root = new DUCE.Resource(); 

            try 
            { 
                //
                // Create the root handle first. 
                //
                target.CreateOrAddRefOnChannel(_captureChannel, DUCE.ResourceType.TYPE_GENERICRENDERTARGET);

                mediaPlayer.CreateOrAddRefOnChannel(_captureChannel, DUCE.ResourceType.TYPE_MEDIAPLAYER); 

                renderData.CreateOrAddRefOnChannel(_captureChannel, DUCE.ResourceType.TYPE_RENDERDATA); 
 
                root.CreateOrAddRefOnChannel(_captureChannel, DUCE.ResourceType.TYPE_VISUAL);
 
                //
                // Initialize our render target.
                //
                DUCE.CompositionTarget.PrintInitialize( 
                    target.Handle,
                    pIRenderTargetBitmap, 
                    (int)width, 
                    (int)height,
                    _captureChannel); 

                //
                // Create the synchronous video slave resource.
                // 
                SendMediaPlayerCommand(
                    _captureChannel, 
                    mediaPlayer.Handle, 
                    false,      // Don't notify the Uce directly
                    false);     // player is not remote. 

                //
                // Construct the render data command and serialize it to the composition engine.
                // 
                unsafe
                { 
                    // 
                    // Set the visual as the root for this generic render target.
                    // 
                    DUCE.CompositionTarget.SetRoot(
                        target.Handle,
                        root.Handle,
                        _captureChannel); 

                    uint cbData = (uint)(sizeof(RenderData.RecordHeader) + sizeof(MILCMD_DRAW_VIDEO)); 
 
                    DUCE.MILCMD_RENDERDATA  renderDataCmd;
 
                    renderDataCmd.Type = MILCMD.MilCmdRenderData;
                    renderDataCmd.Handle = renderData.Handle;
                    renderDataCmd.cbData = cbData;
 
                    _captureChannel.BeginCommand(
                        (byte*)&renderDataCmd, 
                        sizeof(DUCE.MILCMD_RENDERDATA), 
                        (int)cbData);
 
                    RenderData.RecordHeader recordHeader;

                    recordHeader.Size = (int)cbData;
                    recordHeader.Id = MILCMD.MilDrawVideo; 

                    _captureChannel.AppendCommandData((byte *)&recordHeader, sizeof(RenderData.RecordHeader)); 
 
                    //
                    // Provide the render data for the DrawVideo call. 
                    //
                    MILCMD_DRAW_VIDEO drawVideo
                        = new MILCMD_DRAW_VIDEO(
                                (uint)mediaPlayer.Handle, 
                                new Rect(0, 0, width, height));
 
                    // 
                    // Send the command to draw the video.
                    // 
                    _captureChannel.AppendCommandData((byte *)&drawVideo, sizeof(MILCMD_DRAW_VIDEO));

                    _captureChannel.EndCommand();
 
                    //
                    // Set the content of this composition node to be the render data. 
                    // 
                    DUCE.CompositionNode.SetContent(
                        root.Handle, 
                        renderData.Handle,
                        _captureChannel);
                }
 
                //
                // Commit the visual and render data down the capture channel. 
                // 
                _captureChannel.Commit();
 
                //
                // Present on the capture channel, this is so we can start getting
                // frame updates.
                // 
                _captureChannel.Present();
 
                _mediaContext.NotifySyncChannelMessage(_captureChannel); 
            }
            finally 
            {
                _renderTargetRoot = root;
            }
        } 

        ///  
        /// Captures the frame that has been rendered by 
        /// 
        ///  
        /// Critical - calls native code, accesses _captureRenderTargetBitmap.
        /// TreatAsSafe - code just retrieves bitmap which could be done through any
        ///               renderTargetBitmap.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private 
        void 
        CaptureFrame()
        { 
            //
            // Now get the bitmap source from the render target.
            //
            BitmapSourceSafeMILHandle   bitmapSource = null; 

            HRESULT.Check( 
                MILRenderTargetBitmap.GetBitmap( 
                    _captureRenderTargetBitmap,
                    out bitmapSource)); 

            //
            // Clear the old bitmao source.
            // 
            ClearBitmapSource();
 
            // 
            // This becomes our new bitmap source, when the resource on the main channel
            // is updated, 
            //
            _bitmapSource = bitmapSource;
        }
 
        #endregion
 
        #region Event Handlers 

        ///  
        /// When a new frame is received, we need to check if it is remote and then acquire the new frame
        /// from the composition synchronously before passing the NewFrame event up to the
        /// Media player.
        ///  
        private
        void 
        OnNewFrame( 
            object          sender,
            EventArgs       args 
            )
        {
            if (_isRemote && HasNonEmptyVideo)
            { 
                OpenCaptureResources();
 
                // 
                // Create synchronous channel here and a RT bitmap, to capture the frame.
                // 
                CaptureFrame();
            }

            _newFrameHelper.InvokeEvents(sender, args); 
        }
 
        ///  
        /// Fired when the media is opened, we can't open our capture resources until the media is opened
        /// because we won't know the size of the media. 
        /// 
        private
        void
        OnMediaOpened( 
            object          sender,
            EventArgs       args 
            ) 
        {
            // 
            // If this is on a remote channel, we need to open the capture resources.
            //
            if (_isRemote && HasNonEmptyVideo)
            { 
                OpenCaptureResources();
            } 
 
            _mediaOpenedHelper.InvokeEvents(sender, args);
        } 

        #endregion

 
        #region Data Members
 
        ///  
        /// Current volume (ranges from 0 to 1)
        ///  
        private double _volume;

        /// 
        /// Current balance (ranges from -1 (left) to 1 (right) ) 
        /// 
        private double _balance; 
 
        /// 
        /// Current state of mute 
        /// 
        private bool _muted;

        ///  
        /// Whether or not scrubbin is enabled
        ///  
        private bool _scrubbingEnabled; 

        ///  
        /// Unamanaged Media object
        /// 
        /// 
        /// Critical - this is a pointer to an unmanaged object that methods are called directly on 
        /// 
        [SecurityCritical] 
        private SafeMediaHandle _nativeMedia; 

        private MediaEventsHelper _mediaEventsHelper; 

        /// 
        /// Default volume
        ///  
        private const double DEFAULT_VOLUME = 0.5;
 
        ///  
        /// Default balance
        ///  
        private const double DEFAULT_BALANCE = 0;

        private double _speedRatio;
        private bool _paused; 

        private Uri _sourceUri; 
 
        private MediaClock _mediaClock = null;
 
        private Dispatcher _dispatcher = null;

        private BitmapSourceSafeMILHandle _bitmapSource;
 
        private DUCE.MultiChannelResource _bitmapSourceDuceHandle;
 
        private bool _isRemote; 

        // 
        // The channel and render data we use to capture the frames.
        //
        DUCE.Channel    _captureChannel;
        MediaContext    _mediaContext; 
        DUCE.Resource   _renderTargetRoot;
 
        ///  
        /// _captureRenderTargetBitmap should be marked as SecurityCritical,
        /// since it's been obtained under elevation, and if disclosed, could 
        /// allow rendering on elements untrusted parties shouldn't be alloowed.
        /// 
        [SecurityCritical]
        SafeMILHandle   _captureRenderTargetBitmap; 

        private UniqueEventHelper _newFrameHelper = new UniqueEventHelper(); 
        private UniqueEventHelper _mediaOpenedHelper = new UniqueEventHelper(); 

        private const float _defaultDevicePixelsPerInch = 96.0F; 

        /// 
        /// A separate class is needed to register for the ProcessExit event
        /// because MediaPlayerState holds a strong reference to _nativeMedia. 
        /// If a MediaPlayerState method was registered for the ProcessExit
        /// event then MediaPlayerState would not be garbage collected until 
        /// ProcessExit time. 
        /// 
        private class Helper 
        {
            /// 
            /// Critical - this is a weak reference to a pointer to an unmanaged object
            /// on which methods are called directly 
            /// 
            [SecurityCritical] 
            private WeakReference _nativeMedia; 

            ///  
            /// Accesses weak reference to pointer
            /// 
            [SecurityCritical]
            internal 
            Helper(
                SafeMediaHandle nativeMedia 
                ) 
            {
                _nativeMedia = new WeakReference(nativeMedia); 
            }

            /// 
            /// Accesses weak reference to pointer, calls unmanaged code 
            /// 
            [SecurityCritical] 
            internal 
            void
            ProcessExitHandler( 
                object sender,
                EventArgs args
                )
            { 
                SafeMediaHandle nativeMedia = (SafeMediaHandle)_nativeMedia.Target;
                if (nativeMedia != null) 
                { 
                    MILMedia.ProcessExitHandler(nativeMedia);
                } 
            }
        };
        #endregion
    } 

    #endregion 
}; 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------ 
//  Microsoft Avalon
//  Copyright (c) Microsoft Corporation, 2003
//
//  File:       MediaPlayerState.cs 
//
//----------------------------------------------------------------------------- 
using System; 
using System.Threading;
using System.Security; 
using System.Security.Permissions;
using System.Diagnostics;
using System.ComponentModel;
using MS.Internal; 
using MS.Internal.PresentationCore;                        // SecurityHelper
using MS.Win32; 
using System.IO.Packaging; 
using System.Windows.Media.Animation;
using System.Windows.Media; 
using System.Windows.Media.Composition;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using System.Windows.Navigation; 
using System.Runtime.InteropServices;
using System.IO; 
using System.Security.AccessControl;//for semaphore access permissions 
using System.Net;
using Microsoft.Win32; 
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID;
using UnsafeNativeMethods=MS.Win32.PresentationCore.UnsafeNativeMethods;
 
//
// Disable the warnings that C# emmits when it finds pragmas it does not recognize, this is to 
// get rid of false positive PreSharp warning 
//
#pragma warning disable 1634, 1691 


namespace System.Windows.Media
{ 
    #region MediaPlayerState
 
    ///  
    /// MediaPlayerState
    /// Holds all of the local state that is required for playing media. This is 
    /// separated out into a separate class because MediaPlayer needs to be
    /// Animatable, but then that means it needs to be Freezable. However, media
    /// state cannot really be frozan (media piplines progress according to time
    /// and are very expensive), so instead, we make the "Frozen" object copy the 
    /// state object around. Doing this will also help in the remote case where
    /// we need to handle MediaPlayer quite differently on the channel in the 
    /// remote and local cases. 
    /// 
    internal class MediaPlayerState 
    {
        #region Constructors and Finalizers

        ///  
        /// Constructor
        ///  
        ///  
        /// SecurityCritical: This code sets a critical data member (_captureRenderTargetBitmap).
        /// SecurityTreatAsSafe: The critical member is set to a safe value (null). 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal
        MediaPlayerState( 
            MediaPlayer     mediaPlayer
            ) 
        { 
            _dispatcher = mediaPlayer.Dispatcher;
 
            _bitmapSource = null;

            _bitmapSourceDuceHandle = new DUCE.MultiChannelResource();
 
            _captureChannel = null;
 
            _captureRenderTargetBitmap = null; 

            _mediaContext = null; 

            _renderTargetRoot = DUCE.Resource.Null;

            Init(); 

            CreateMedia(mediaPlayer); 
 
            //
            // We need to know about new frames when they are sent so that we can 
            // capture the image data in the synchronous case.
            //
            _mediaEventsHelper.NewFrame += new EventHandler(OnNewFrame);
 
            //
            // Opened is actually fired when the media is prerolled. 
            // 
            _mediaEventsHelper.MediaPrerolled += new EventHandler(OnMediaOpened);
        } 

        //

        ///  
        /// Initialize local variables to their default state. After a close we want to restore this too, same as
        /// after construction. 
        ///  
        private
        void 
        Init()
        {
            _volume = DEFAULT_VOLUME;
            _balance = DEFAULT_BALANCE; 
            _speedRatio = 1.0;
            _paused = false; 
            _muted = false; 
            _sourceUri = null;
            _scrubbingEnabled = false; 
            _isRemote = false;

            //
            // Need to clear our bitmap source. 
            //
            ClearBitmapSource(); 
 
            //
            // Need to close our synchronous render infrastructure. 
            //
            CloseCaptureResources();
        }
 
        #endregion
 
        #region Public Methods 

        ///  
        /// Internal IsBuffering
        /// 
        /// 
        ///     Critical: This calls into unmanaged code and also acceses _nativemedia 
        ///     TreatAsSafe: This information about whether buffering is on is safe to expose
        ///  
        internal bool IsBuffering 
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            {
                VerifyAPI();
                bool isBuffering = false; 
                HRESULT.Check(MILMedia.IsBuffering(_nativeMedia, ref isBuffering));
                return isBuffering; 
            } 
        }
 
        /// 
        /// Internal CanPause
        /// 
        ///  
        ///     Critical: This is critical because it acceses _nativemedia and calls into unmanaged code
        ///     TreatAsSafe: This is safe to expose since giving out information about 
        ///     whether media can be paused is safe 
        /// 
        internal bool CanPause 
        {
            [SecurityCritical, SecurityTreatAsSafe]
            get
            { 
                VerifyAPI();
                bool canPause = false; 
                HRESULT.Check(MILMedia.CanPause(_nativeMedia, ref canPause)); 
                return canPause;
            } 
        }

        /// 
        /// Internal DownloadProgress 
        /// 
        ///  
        ///     Critical: This is critical it calls into unmanged code and accesses _nativeMedia 
        ///     TreatAsSafe: This is safe because the critical resource is not exposed and
        ///     returning download progress is safe 
        /// 
        internal double DownloadProgress
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            { 
                VerifyAPI(); 
                double downloadProgress = 0;
                HRESULT.Check(MILMedia.GetDownloadProgress(_nativeMedia, ref downloadProgress)); 
                return downloadProgress;
            }
        }
 
        /// 
        /// Internal BufferingProgress 
        ///  
        /// 
        ///     Critical: This is critical it calls into unmanged code and accesses _nativeMedia 
        ///     TreatAsSafe: This is safe because the critical resource is not exposed and
        ///     returning buffering progress is safe
        /// 
        internal double BufferingProgress 
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get 
            {
                VerifyAPI(); 
                double bufferingProgress = 0;
                HRESULT.Check(MILMedia.GetBufferingProgress(_nativeMedia, ref bufferingProgress));
                return bufferingProgress;
            } 
        }
 
        ///  
        /// Returns the Height
        ///  
        /// 
        ///     Critical: This is critical it calls into unmanged code and accesses _nativeMedia
        ///     TreatAsSafe: This is safe because the critical resource is not exposed and
        ///     returning natural video height is safe 
        /// 
        internal Int32 NaturalVideoHeight 
        { 
            [SecurityCritical, SecurityTreatAsSafe]
            get 
            {
                VerifyAPI();

                UInt32 height = 0; 

                HRESULT.Check(MILMedia.GetNaturalHeight(_nativeMedia, ref height)); 
                return (Int32)height; 
            }
        } 

        /// 
        /// Returns the Width
        ///  
        /// 
        ///     Critical: This is critical it calls into unmanged code and accesses _nativeMedia 
        ///     TreatAsSafe: This is safe because the critical resource is not exposed and 
        ///     returning natural video width is safe
        ///  
        internal Int32 NaturalVideoWidth
        {
            [SecurityCritical, SecurityTreatAsSafe]
            get 
            {
                VerifyAPI(); 
 
                UInt32 width = 0;
 
                HRESULT.Check(MILMedia.GetNaturalWidth(_nativeMedia, ref width));
                return (Int32)width;
            }
        } 

        ///  
        /// If media has audio content 
        /// 
        ///  
        ///     Critical: This is critical it calls into unmanged code and accesses _nativeMedia
        ///     TreatAsSafe: This is safe because the critical resource is not exposed and
        ///     returning whether media has audio is safe
        ///  
        internal bool HasAudio
        { 
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            { 
                VerifyAPI();

                bool hasAudio = true;
 
                HRESULT.Check(MILMedia.HasAudio(_nativeMedia, ref hasAudio));
                return hasAudio; 
            } 
        }
 
        /// 
        /// If the media has video content
        /// 
        ///  
        ///     Critical: This is critical it calls into unmanged code and accesses _nativeMedia
        ///     TreatAsSafe: This is safe because the critical resource is not exposed and 
        ///     returning whether media has video is safe 
        /// 
        internal bool HasVideo 
        {
            [SecurityCritical, SecurityTreatAsSafe]
            get
            { 
                VerifyAPI();
 
                bool hasVideo = false; 

                HRESULT.Check(MILMedia.HasVideo(_nativeMedia, ref hasVideo)); 
                return hasVideo;
            }
        }
 
        /// 
        /// Location of the media to play. Open opens the media, this property 
        /// allows the source that is currently playing to be retrieved. 
        /// 
        internal Uri Source 
        {
            get
            {
                VerifyAPI(); 

                return _sourceUri; 
            } 
        }
 
        /// 
        /// Internal Get Volume
        /// 
        ///  
        ///     Critical: This is critical because it calls into unmanged code and accesses _nativeMedia
        ///     TreatAsSafe: This is safe because the critical resource is not exposed and 
        ///     returning volume ratio is safe and so also is setting it 
        /// 
        internal double Volume 
        {
            [SecurityCritical, SecurityTreatAsSafe]
            get
            { 

                VerifyAPI(); 
 
                return _volume;
            } 
            [SecurityCritical, SecurityTreatAsSafe]
            set
            {
                VerifyAPI(); 
                if (Double.IsNaN(value))
                { 
                    throw new ArgumentException(SR.Get(SRID.ParameterValueCannotBeNaN), "value"); 
                }
 
                if (DoubleUtil.GreaterThanOrClose(value, 1))
                {
                    value = 1;
                } 
                else if (DoubleUtil.LessThanOrClose(value, 0))
                { 
                    value = 0; 
                }
 
                // We only want to set the volume if the current cached volume is not the same
                // No need to do extra work.
                if (!DoubleUtil.AreClose(_volume, value))
                { 
                    if (!_muted)
                    { 
                        int hr = MILMedia.SetVolume(_nativeMedia, value); 

                        HRESULT.Check(hr); 

                        // value is changing
                        _volume = value;
                    } 
                    else
                    { 
                        // If we are muted, cache the volume 
                        _volume = value;
                    } 
                }
            }
        }
 
        /// 
        /// Internal Get Balance 
        ///  
        /// 
        ///     Critical: This is accesses the native media. 
        ///     TreatAsSafe: This is safe because the act of adjusting the balance is a safe one.
        /// 
        internal double Balance
        { 
            [SecurityCritical, SecurityTreatAsSafe]
            get 
            { 

                VerifyAPI(); 

                return _balance;
            }
            [SecurityCritical, SecurityTreatAsSafe] 
            set
            { 
                VerifyAPI(); 
                if (Double.IsNaN(value))
                { 
                    throw new ArgumentException(SR.Get(SRID.ParameterValueCannotBeNaN), "value");
                }

                if (DoubleUtil.GreaterThanOrClose(value, 1)) 
                {
                    value = 1; 
                } 
                else if (DoubleUtil.LessThanOrClose(value, -1))
                { 
                    value = -1;
                }

                // We only want to set the balance if the current cached balance 
                // is not the same. No need to do extra work.
                if (!DoubleUtil.AreClose(_balance, value)) 
                { 
                    int hr = MILMedia.SetBalance(_nativeMedia, value);
 
                    HRESULT.Check(hr);

                    // value is changing
                    _balance = value; 
                }
            } 
        } 

        ///  
        /// Whether or not scrubbing is enabled
        /// 
        /// 
        ///     Critical: This accesses the native media. 
        ///     TreatAsSafe: This is safe because it's safe to adjust whether or not scrubbing is enabled
        ///  
        internal bool ScrubbingEnabled 
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            {
                VerifyAPI();
                return _scrubbingEnabled; 
            }
            [SecurityCritical, SecurityTreatAsSafe] 
            set 
            {
                VerifyAPI(); 
                if (value != _scrubbingEnabled)
                {
                    HRESULT.Check(MILMedia.SetIsScrubbingEnabled(_nativeMedia, value));
                    _scrubbingEnabled = value; 
                }
            } 
        } 

        ///  
        /// Internal Get Mute
        /// 
        internal bool IsMuted
        { 
            get
            { 
                VerifyAPI(); 
                return _muted;
            } 
            set
            {
                VerifyAPI();
 
                // we need to store the volume since this.Volume will change the cached value
                double volume = _volume; 
 
                if (value && !_muted)
                { 
                    // Going from Unmuted -> Muted

                    // Set the volume to 0
                    this.Volume = 0; 
                    _muted = true;
 
                    // make sure cached volume is previous value 
                    _volume = volume;
                } 
                else if (!value && _muted)
                {
                    // Going from Muted -> Unmuted
 
                    _muted = false;
 
                    // set cached volume to 0 since this. Volume will only change volume 
                    // if cached volume and new volume differ
                    _volume = 0; 

                    // set volume to old cached value, which will also update our current cached value
                    this.Volume = volume;
                } 
            }
        } 
 
        /// 
        ///     Critical: This is critical it calls into unmanged code and accesses _nativeMedia 
        ///     TreatAsSafe: This is safe because the critical resource is not exposed and
        ///     returning natural duration is safe
        /// 
        internal Duration NaturalDuration 
        {
            [SecurityCritical, SecurityTreatAsSafe] 
            get 
            {
                VerifyAPI(); 

                long mediaLength = 0;
                HRESULT.Check(MILMedia.GetMediaLength(_nativeMedia, ref mediaLength));
                if (mediaLength == 0) 
                {
                    return Duration.Automatic; 
                } 
                else
                { 
                    return new Duration(TimeSpan.FromTicks(mediaLength));
                }
            }
        } 

        ///  
        /// Seek to specified position 
        /// 
        internal TimeSpan Position 
        {
            set
            {
                VerifyAPI(); 

                VerifyNotControlledByClock(); 
 
                SetPosition(value);
            } 
            get
            {
                VerifyAPI();
 
                return GetPosition();
            } 
        } 

        ///  
        /// The current speed. This cannot be changed if a clock is controlling this player
        /// 
        internal double SpeedRatio
        { 
            get
            { 
                VerifyAPI(); 

                return _speedRatio; 
            }
            set
            {
                VerifyAPI(); 
                VerifyNotControlledByClock();
 
                if (value < 0) 
                {
                    value = 0; // we clamp negative values to 0 
                }

                SetSpeedRatio(value);
            } 
        }
 
        ///  
        /// The dispatcher, this is actually derived from the media player
        /// on construction. 
        /// 
        internal Dispatcher Dispatcher
        {
            get 
            {
                return _dispatcher; 
            } 
        }
 

        #endregion

        #region EventHandlers 

        ///  
        /// Raised when there is an error opening or playing media 
        /// 
        internal event EventHandler MediaFailed 
        {
            add
            {
                VerifyAPI(); 
                _mediaEventsHelper.MediaFailed += value;
            } 
            remove 
            {
                VerifyAPI(); 
                _mediaEventsHelper.MediaFailed -= value;
            }
        }
 
        /// 
        /// Raised when the media has been opened. 
        ///  
        internal event EventHandler MediaOpened
        { 
            add
            {
                VerifyAPI();
 
                _mediaOpenedHelper.AddEvent(value);
            } 
            remove 
            {
                VerifyAPI(); 

                _mediaOpenedHelper.RemoveEvent(value);
            }
        } 

 
        ///  
        /// Raised when the media has finished.
        ///  
        internal event EventHandler MediaEnded
        {
            add
            { 
                VerifyAPI();
                _mediaEventsHelper.MediaEnded += value; 
            } 
            remove
            { 
                VerifyAPI();
                _mediaEventsHelper.MediaEnded -= value;
            }
        } 

 
        ///  
        /// Raised when media begins buffering.
        ///  
        internal event EventHandler BufferingStarted
        {
            add
            { 
                VerifyAPI();
                _mediaEventsHelper.BufferingStarted += value; 
            } 
            remove
            { 
                VerifyAPI();
                _mediaEventsHelper.BufferingStarted -= value;
            }
        } 

 
        ///  
        /// Raised when media finishes buffering.
        ///  
        internal event EventHandler BufferingEnded
        {
            add
            { 
                VerifyAPI();
 
                _mediaEventsHelper.BufferingEnded += value; 
            }
            remove 
            {
                VerifyAPI();

                _mediaEventsHelper.BufferingEnded -= value; 
            }
        } 
 
        /// 
        /// Raised when a script command embedded in the media is encountered. 
        /// 
        internal event EventHandler ScriptCommand
        {
            add 
            {
                VerifyAPI(); 
                _mediaEventsHelper.ScriptCommand += value; 
            }
            remove 
            {
                VerifyAPI();
                _mediaEventsHelper.ScriptCommand -= value;
            } 
        }
 
        ///  
        /// Raised when a new frame in the media is encountered, we only
        /// send one new frame per AddRefOnChannel in synchronous mode only. 
        /// 
        internal event EventHandler NewFrame
        {
            add 
            {
                VerifyAPI(); 
 
                _newFrameHelper.AddEvent(value);
            } 

            remove
            {
                VerifyAPI(); 

                _newFrameHelper.RemoveEvent(value); 
            } 
        }
 
        #endregion

        #region Clock dependent properties and methods
 
        /// 
        /// The clock driving this instance of media 
        ///  
        internal MediaClock Clock
        { 
            get
            {
                VerifyAPI();
                return _mediaClock; 
            }
        } 
 
        internal
        void 
        SetClock(
            MediaClock  clock,
            MediaPlayer player
            ) 
        {
            VerifyAPI(); 
            MediaClock oldClock = _mediaClock; 
            MediaClock newClock = clock;
 
            // Avoid infinite loops
            if (oldClock != newClock)
            {
                _mediaClock = newClock; 

                // Disassociate the old clock 
                if (oldClock != null) 
                {
                    oldClock.Player = null; 
                }

                // Associate the new clock;
                if (newClock != null) 
                {
                    newClock.Player = player; 
                } 

                // According to the spec, setting the Clock to null 
                // should set the Source to null
                if (newClock == null)
                {
                    Open(null); 
                }
            } 
        } 

        ///  
        /// Open the media, at this point the underlying native resources are
        /// created. The media player cannot be controlled when it isn't opened.
        /// 
        internal 
        void
        Open( 
            Uri      source 
            )
        { 
            VerifyAPI();
            VerifyNotControlledByClock();

            SetSource(source); 

            // Workaround for bug 107397: Resuing one instance of MediaElement and 
            // calling play() wont result in seek to zero, Media Freezes.  Ensure 
            // we set Media to play from the beginning.
            SetPosition(TimeSpan.Zero); 
        }

        /// 
        /// Begin playback. This operation is not allowed if a clock is 
        /// controlling this player
        ///  
        internal void Play() 
        {
            VerifyAPI(); 
            VerifyNotControlledByClock();

            _paused = false;
            PrivateSpeedRatio = SpeedRatio; 
        }
 
        ///  
        /// Halt playback at current position. This operation is not allowed if
        /// a clock is controlling this player 
        /// 
        internal void Pause()
        {
            VerifyAPI(); 
            VerifyNotControlledByClock();
 
            _paused = true; 
            PrivateSpeedRatio = 0;
        } 

        /// 
        /// Halt playback and seek to the beginning of media. This operation is
        /// not allowed if a clock is controlling this player 
        /// 
        internal void Stop() 
        { 
            VerifyAPI();
            VerifyNotControlledByClock(); 

            Pause();
            Position = TimeSpan.FromTicks(0);
        } 

        ///  
        /// Closes the underlying media. This de-allocates all of the native resources in 
        /// the media. The mediaplayer can be opened again by calling the Open method.
        ///  
        /// 
        ///     Critical: This calls into unmanaged code and also acceses _nativemedia.
        ///     TreatAsSafe: Intrinsically safe to close media.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        internal 
        void 
        Close()
        { 
            VerifyAPI();

            VerifyNotControlledByClock();
 
            HRESULT.Check(MILMedia.Close(_nativeMedia));
 
            // 
            // Once we successfully close, we don't have a clock anymore.
            // Assign the property so that the clock is disconnected from the 
            // player as well as the player from the clock.
            //
            SetClock(null, null);
 
            Init();
        } 
 
        /// 
        /// Sends a command to play the given media. 
        /// 
        /// 
        ///     Critical: This calls into unmanaged code and also acceses _nativemedia.
        ///     TreatAsSafe: Media Command merely binds resource to native player. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal 
        void
        SendCommandMedia( 
            DUCE.Channel            channel,
            DUCE.ResourceHandle     handle,
            bool                    notifyUceDirectly,
            bool                    isRemote 
            )
        { 
            _isRemote = isRemote; 

            // 
            // If this is remote, then we want to marshal over the
            // bitmap source we captured from the media (if it
            // is available).
            // 
            if (isRemote)
            { 
                // 
                // If we have a bitmap source and the bitmap source handle
                // isn't on this channel, then create it. 
                //
                if (_bitmapSource != null)
                {
                    // 
                    // If we have a bitmap source and we haven't created
                    // the the _duceHandle, then create it now. 
                    // 
                    if (!_bitmapSourceDuceHandle.IsOnChannel(channel))
                    { 
                        //
                        // Create the bitap source duce handle.
                        //
                        _bitmapSourceDuceHandle.CreateOrAddRefOnChannel(channel, DUCE.ResourceType.TYPE_BITMAPSOURCE); 
                    }
 
                    // 
                    // Send the bitmap source down the channel.
                    // 
                    channel.SendCommandBitmapSource(
                                _bitmapSourceDuceHandle.GetHandle(channel),
                                _bitmapSource,
                                true,       // share the bitmap 
                                true);      // system memory bitmap.
                } 
            } 
            else
            { 
                //
                // If we are actually moved onto a local channel, we don't
                // wan't our bitmap source lieing around.
                // 
                ClearBitmapSource();
 
                // 
                // Make sure that the capture resources are closed.
                // 
                CloseCaptureResources();
            }

            SendMediaPlayerCommand( 
                channel,
                handle, 
                notifyUceDirectly, 
                isRemote);
 

            //
            // Independently, tell the native media that we need to update the UI, the
            // reason we do this directly through the player is that effects can immediately 
            // remove the channel on us and hence media might not get a chance to see
            // the media player resource. 
            // 
            if (!notifyUceDirectly)
            { 
                NeedUIFrameUpdate();

                //
                // We need to force a present on each pass otherwise we won't get any 
                // frame updates.
                // 
                // 
                // If this is remote, we want to start capturing the frame if we have
                // been opened already. 
                //
                if (isRemote && HasNonEmptyVideo)
                {
                    OpenCaptureResources(); 

                    _captureChannel.Present(); 
 
                    _mediaContext.NotifySyncChannelMessage(_captureChannel);
                } 
            }
        }

        private 
        bool
        HasNonEmptyVideo 
        { 
            get
            { 
                return NaturalVideoWidth != 0 && NaturalVideoHeight != 0;
            }
        }
 
        /// 
        /// Sends a request to the media player to reserve a UI frame for notification. 
        ///  
        /// 
        ///     Critical: This calls into unmanaged code and also acceses _nativemedia. 
        ///     TreatAsSafe: Asking for a frame update is inherently safe.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private 
        void
        NeedUIFrameUpdate() 
        { 
            VerifyAPI();
 
            HRESULT.Check(MILMedia.NeedUIFrameUpdate(_nativeMedia));
        }

 
        /// 
        /// Sends a command to play the given media. 
        ///  
        /// 
        ///     Critical: This calls into unmanaged code and also acceses _nativemedia. 
        ///     TreatAsSafe: Media Command merely binds resource to native player.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal 
        void
        ReleaseOnChannel( 
            DUCE.Channel            channel 
            )
        { 
            //
            // If the bitmap source handle is on this channel, then release it.
            //
            if (_bitmapSourceDuceHandle.IsOnChannel(channel)) 
            {
                _bitmapSourceDuceHandle.ReleaseOnChannel(channel); 
            } 

            // 
            // Remove the capture resources.
            //
            CloseCaptureResources();
        } 

        #endregion 
 
        #region Private Methods
 
        /// 
        /// Create the unmanaged media resources
        /// 
        ///  
        /// Critical - calls unmanaged code, access pointer parameters. It instantiates
        ///            windows media player 
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private void CreateMedia(MediaPlayer mediaPlayer) 
        {
            CheckMediaDisabledFlags();

            SafeMILHandle unmanagedProxy = null; 
            MediaEventsHelper.CreateMediaEventsHelper(mediaPlayer, out _mediaEventsHelper, out unmanagedProxy);
            try 
            { 
                using (FactoryMaker myFactory = new FactoryMaker())
                { 
                    HRESULT.Check(UnsafeNativeMethods.MILFactory2.CreateMediaPlayer(
                            myFactory.FactoryPtr,
                            unmanagedProxy,
                            SecurityHelper.CallerHasMediaPermission(MediaPermissionAudio.AllAudio, MediaPermissionVideo.AllVideo, MediaPermissionImage.NoImage), 
                            MediaSystem.DeviceId,
                            out _nativeMedia 
                            )); 
                }
            } 
            catch
            {
                if (_nativeMedia != null && !_nativeMedia.IsInvalid)
                { 
                    _nativeMedia.Close();
                } 
 
                throw;
            } 

            Helper helper = new Helper(_nativeMedia);
            AppDomain.CurrentDomain.ProcessExit += helper.ProcessExitHandler;
        } 

        ///  
        /// Open Media 
        /// 
        ///  
        /// Critical - access critical resource (_nativeMedia), access local file system
        /// and also stores the path to base directory in a local variable. It also asserts
        /// to allow FileIO to local directory. It calls GetBaseDirectory, that returns sensitive information.
        /// TreatAsSafe: This path is sent to the unmanaged layer to be opened. Also it demands 
        /// fileio for absolute paths and web permissions for files on a server. It only lets you access
        /// files in current directory and does not expose the location of current directory 
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        private void OpenMedia(Uri source) 
        {
            string toOpen = null;

            if (source != null && source.IsAbsoluteUri && source.Scheme == PackUriHelper.UriSchemePack) 
            {
                try 
                { 
                    source = BaseUriHelper.ConvertPackUriToAbsoluteExternallyVisibleUri(source);
                } 
                catch (InvalidOperationException)
                {
                    source = null;
                    _mediaEventsHelper.RaiseMediaFailed(new System.NotSupportedException(SR.Get(SRID.Media_PackURIsAreNotSupported, null))); 
                }
            } 
 
            // Setting a null source effectively disconects the MediaElement.
            if (source != null) 
            {
                // keep whether we asserted permissions or not
                bool elevated = false;
 
                // get the base directory of the application; never expose this
                Uri appBase = SecurityHelper.GetBaseDirectory(AppDomain.CurrentDomain); 
 
                // this extracts the URI to open
                Uri uriToOpen = ResolveUri(source, appBase); 

                // access is allowed in the following cases (only 1 & 2 require elevation):
                // 1) to any HTTPS media if app is NOT coming from HTTPS
                // 2) to URI in the current directory of the fusion cache 
                // 3) to site of origin media
                if (SecurityHelper.AreStringTypesEqual(uriToOpen.Scheme, Uri.UriSchemeHttps)) 
                { 
                    // target is HTTPS. Then, elevate ONLY if we are NOT coming from HTTPS (=XDomain HTTPS app to HTTPS media disallowed)
                    Uri appDeploymentUri = SecurityHelper.ExtractUriForClickOnceDeployedApp(); 
                    if (!SecurityHelper.AreStringTypesEqual(appDeploymentUri.Scheme, Uri.UriSchemeHttps))
                    {
                        new WebPermission(NetworkAccess.Connect, BindUriHelper.UriToString(uriToOpen)).Assert();
                        elevated = true; 
                    }
                } 
                else 
                {
                    // elevate to allow access to media in the app's directory in the fusion cache. 
                    new FileIOPermission(FileIOPermissionAccess.Read, appBase.LocalPath).Assert();// BlessedAssert
                    elevated = true;
                }
 
                // demand permissions. if demands succeds, it means we are in one of the cases above.
                try 
                { 
                    toOpen  = DemandPermissions(uriToOpen);
                } 
                finally
                {
                    if (elevated)
                    { 
                        CodeAccessPermission.RevertAssert();
                    } 
                } 
            }
            else 
            {
                toOpen = null;
            }
 
            // We pass in exact same URI for which we demanded permissions so that we can be sure
            // there is no discrepancy between the two. 
            HRESULT.Check(MILMedia.Open(_nativeMedia, toOpen)); 
        }
 
        /// 
        ///     Critical: This code elevates to read registry
        ///     TreatAsSafe: Detecting whether media is disabled is a safe operation
        ///  
        [SecurityCritical,SecurityTreatAsSafe]
        private void CheckMediaDisabledFlags() 
        { 
            if (SafeSecurityHelper.IsFeatureDisabled(SafeSecurityHelper.KeyToRead.MediaAudioOrVideoDisable))
            { 
                // in case the registry key is '1' then demand
                //Demand media permission here for Video or Audio
                // Issue: 1232606 need to fix once clr has the media permissions
                SecurityHelper.DemandMediaPermission(MediaPermissionAudio.AllAudio, 
                                                     MediaPermissionVideo.AllVideo,
                                                     MediaPermissionImage.NoImage); 
            } 
        }
 
        /// 
        ///     Critical: This code returns the base directory of the app as a URI
        ///     IT constructs a Uri based on relative and absolute URI
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private Uri ResolveUri(Uri uri, Uri appBase) 
        { 
            if (uri.IsAbsoluteUri)
            { 
                return uri;
            }
            else
            { 
                return new Uri(appBase, uri);
            } 
        } 

        // returns the exact string on which we demanded permissions 

        /// 
        ///     Critical: This code is used to safeguard against various forms of attacks
        ///     to restrict access to loose file passed as relative path in the application 
        ///     base direcory
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        private string DemandPermissions(Uri absoluteUri)
        { 
            Debug.Assert(absoluteUri.IsAbsoluteUri);
            string toOpen = BindUriHelper.UriToString(absoluteUri);
            int targetZone = SecurityHelper.MapUrlToZoneWrapper(absoluteUri);
 
            if (targetZone == NativeMethods.URLZONE_LOCAL_MACHINE)
            { 
                // go here only for files and not for UNC 
                if (absoluteUri.IsFile)
                { 
                    // Please note this pattern is unique and NEEDS TO EXIST , it prevents
                    // access to any folder but the one where the app is running from.
                    // PLEASE DO NOT REMOVE THIS DEMAND AND THE ASSERT IN THE CALLING CODE
                    toOpen = absoluteUri.LocalPath; 
                    (new FileIOPermission(FileIOPermissionAccess.Read, toOpen)).Demand();
                } 
            } 
            else //Any other zone
            { 
                // UNC path pointing to a file (We filter for `http://intranet)
                if (absoluteUri.IsFile && absoluteUri.IsUnc)
                {
                    // perform checks for UNC content 
                    SecurityHelper.EnforceUncContentAccessRules(absoluteUri);
 
                    // In this case we first check to see if the consumer has media permissions for 
                    // safe media (Site of Origin + Cross domain).
                    if (!SecurityHelper.CallerHasMediaPermission(MediaPermissionAudio.SafeAudio, 
                                                                 MediaPermissionVideo.SafeVideo,
                                                                 MediaPermissionImage.NoImage))
                    {
                        // if he does not then we demand web permission to allow access only to site of origin 
                        (new FileIOPermission(FileIOPermissionAccess.Read, toOpen)).Demand();
                    } 
 
                }
                else // Any other path 
                {
                    // In this case we first check to see if the consumer has media permissions for
                    // safe media (Site of Origin + Cross domain).
                    if (absoluteUri.Scheme != Uri.UriSchemeHttps) 
                    {
                        //accessing non https content from an https app is disallowed 
                        SecurityHelper.BlockCrossDomainForHttpsApps(absoluteUri); 
                        if (!SecurityHelper.CallerHasMediaPermission(MediaPermissionAudio.SafeAudio,
                                                                     MediaPermissionVideo.SafeVideo, 
                                                                     MediaPermissionImage.NoImage))
                        {
                            // if he does not then we demand web permission to allow access only to site of origin
                            (new WebPermission(NetworkAccess.Connect, toOpen)).Demand(); 
                        }
                    } 
                    else// This is the case where target content is HTTPS 
                    {
                        (new WebPermission(NetworkAccess.Connect, toOpen)).Demand(); 
                    }

                }
            } 

            return toOpen; 
        } 

        ///  
        /// Seek to specified position (in 100 nanosecond ticks)
        /// 
        /// 
        /// Critical - access critical resource (_nativeMedia) 
        /// TreatAsSafe - critical resource isn't modified or handed out
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        internal void SetPosition(TimeSpan value)
        { 
            VerifyAPI();

            HRESULT.Check(MILMedia.SetPosition(_nativeMedia, value.Ticks));
        } 

        ///  
        /// get the current position (in 100 nanosecond ticks) 
        /// 
        ///  
        /// Critical - access critical resource (_nativeMedia)
        /// TreatAsSafe - critical resource isn't modified or handed out
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private TimeSpan GetPosition()
        { 
            VerifyAPI(); 

            long position = 0; 
            HRESULT.Check(MILMedia.GetPosition(_nativeMedia, ref position));
            return TimeSpan.FromTicks(position);
        }
 
        /// 
        /// Critical - access critical resource (_nativeMedia) 
        /// TreatAsSafe - critical resource isn't modified or handed out 
        /// 
        private double PrivateSpeedRatio 
        {
            [SecurityCritical, SecurityTreatAsSafe]
            set
            { 
                VerifyAPI();
 
                if (Double.IsNaN(value)) 
                {
                    throw new ArgumentException(SR.Get(SRID.ParameterValueCannotBeNaN), "value"); 
                }

                HRESULT.Check(MILMedia.SetRate(_nativeMedia, value));
            } 
        }
 
        // 
        // Set the current speed.
        // 
        internal void SetSpeedRatio(double value)
        {
            _speedRatio = value;
 
            //
            // We don't change the speed if we are paused, unless we are in 
            // clock mode, which overrides paused mode. 
            //
            if (!_paused || _mediaClock != null) 
            {
                PrivateSpeedRatio = _speedRatio;
            }
        } 

        ///  
        /// Sets the source of the media (and opens it), without checking whether 
        /// we are under clock control. This is called by the clock.
        ///  
        internal
        void
        SetSource(
            Uri      source 
            )
        { 
            if (source != _sourceUri) 
            {
                OpenMedia(source); 

                //
                // Only assign the source uri if the OpenMedia succeeds.
                // 
                _sourceUri = source;
            } 
        } 

 
        /// 
        /// Verifies this object is in an accessible state, and that we
        /// are being called from the correct thread. This method should
        /// be the first thing called from any internal method. 
        /// 
        ///  
        /// Critical - access critical resource (_nativeMedia) 
        /// TreatAsSafe - critical resource isn't modified or handed out
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private void VerifyAPI()
        {
            // 
            // We create _nativeMedia in the constructor, so it should always
            // be initialized. 
            // 
            Debug.Assert(_nativeMedia != null && !_nativeMedia.IsInvalid);
 
            //
            // We only allow calls to any media object on the UI thread.
            //
            _dispatcher.VerifyAccess(); 

            if (_nativeMedia == null || _nativeMedia.IsInvalid) 
            { 
                throw new System.NotSupportedException(SR.Get(SRID.Image_BadVersion));
            } 
        }

        /// 
        /// Verifies that this player is not currently controlled by a clock. Some actions are 
        /// invalid while we are under clock control.
        ///  
        private 
        void
        VerifyNotControlledByClock() 
        {
            if (Clock != null)
            {
                throw new InvalidOperationException(SR.Get(SRID.Media_NotAllowedWhileTimingEngineInControl)); 
            }
        } 
 
        /// 
        /// Clears the bitmap source. 
        /// 
        /// 
        /// Critical - calls LinkDemand-protected SafeHandle.Close
        /// TreatAsSafe - doesn't accept an arbitrary handle to close 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private 
        void
        ClearBitmapSource() 
        {
            //
            // Close the bitmap source,
            // 
            if (_bitmapSource != null)
            { 
                _bitmapSource.Close(); 

                _bitmapSource = null; 
            }
        }

        ///  
        /// SendMediaPlayerCommand
        ///               SecurityNote 
        ///  
        /// Critical - access critical resource (_nativeMedia)
        /// TreatAsSafe - critical resource is treated like any other image. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private
        void 
        SendMediaPlayerCommand(
            DUCE.Channel            channel, 
            DUCE.ResourceHandle     handle, 
            bool                    notifyUceDirectly,
            bool                    isRemote 
            )
        {
//
// This is an interrop call, but, it does not set a last error being a COM call. So, suppress the 
// presharp warning about losing last error.
// 
#pragma warning disable 6523 

            // 
            // AddRef to ensure the media player stays alive during transport, even if the
            // MediaPlayer goes away.  The slave video resource takes ownership of this AddRef.
            // Note there is still a gray danger zone here -- if the channel command is lost
            // this reference won't be cleaned up. 
            //
            // 
 

 

            if (!isRemote)
            {
                UnsafeNativeMethods.MILUnknown.AddRef(_nativeMedia); 
            }
 
            channel.SendCommandMedia( 
                handle,
                _nativeMedia, 
                isRemote ? _bitmapSourceDuceHandle.GetHandle(channel) : DUCE.ResourceHandle.Null,
                notifyUceDirectly,
                isRemote);
 
#pragma warning restore 6523
        } 
 
        /// 
        /// Close all of the capture resources. 
        /// 
        /// 
        /// SecurityCritical: This code references critical data (_captureRenderTargetBitmap).
        /// SecurityTreatAsSafe: It just checks for a null value. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private 
        void
        CloseCaptureResources() 
        {
            //
            // We don't clear our bitmap source because this can result on us
            // getting a channel change without a bitmap source. This is bad. 
            //
            if (null != _captureRenderTargetBitmap) 
            { 
                CloseRenderTarget();
            } 

            if (null != _captureChannel)
            {
                CloseSyncChannel(); 
            }
        } 
 
        /// 
        /// Open all of the capture resources we need 
        /// 
        /// 
        /// SecurityCritical: This code references critical data (_captureRenderTargetBitmap).
        /// SecurityTreatAsSafe: It just checks for a null value. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private 
        void
        OpenCaptureResources() 
        {
            if (null == _captureChannel)
            {
                OpenSyncChannel(); 
            }
 
            if (null == _captureRenderTargetBitmap) 
            {
                OpenRenderTarget(); 
            }
        }

        ///  
        /// Open the synchronous channel.
        ///  
        private 
        void
        OpenSyncChannel() 
        {
            _mediaContext = MediaContext.CurrentMediaContext;

            // 
            // Allocate a synchronous channel to receive the result from
            // the media player. 
            // 
            _captureChannel = _mediaContext.AllocateSyncChannel();
        } 

        /// 
        /// Close the synchronous channel.
        ///  
        private
        void 
        CloseSyncChannel() 
        {
            _mediaContext.ReleaseSyncChannel(_captureChannel); 

            _mediaContext = null;

            _captureChannel = null; 
        }
 
        ///  
        /// Close the render target
        ///  
        /// 
        /// Critical - calls LinkDemand-protected SafeHandle.Close.  Accesses _captureRenderTargetBitmap.
        /// TreatAsSafe - doesn't accept an arbitrary handle to close.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private 
        void 
        CloseRenderTarget()
        { 
            _captureRenderTargetBitmap.Close();

            _captureRenderTargetBitmap = null;
 
            if (!_renderTargetRoot.Handle.IsNull)
            { 
                DUCE.CompositionNode.RemoveAllChildren(_renderTargetRoot.Handle, _captureChannel); 

                _renderTargetRoot.ReleaseOnChannel(_captureChannel); 
            }
        }

        ///  
        /// Captures the frame from the native media by creating a synchrous channel
        /// with a RTBitmap and acquiring the image source. 
        ///  
        /// 
        /// Critical - access critical resource (_nativeMedia, renderTargetBitmap, _captureRenderTargetBitmap). 
        /// TreatAsSafe - critical resource is treated like any other image (e.g. DrawImage code):
        /// We are sending images because we need to send them across the wire if we are drawing video remotely.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private
        void 
        OpenRenderTarget() 
        {
            uint width = (uint)NaturalVideoWidth; 
            uint height = (uint)NaturalVideoHeight;

            Debug.Assert(width != 0 && height != 0);
 
            using(FactoryMaker myFactory = new FactoryMaker())
            { 
                HRESULT.Check( 
                    UnsafeNativeMethods.MILFactory2.CreateBitmapRenderTarget(
                        myFactory.FactoryPtr, 
                        width,
                        height,
                        PixelFormatEnum.Pbgra32,
                        _defaultDevicePixelsPerInch, 
                        _defaultDevicePixelsPerInch,
                        MILRTInitializationFlags.MIL_RT_INITIALIZE_DEFAULT, 
                        out _captureRenderTargetBitmap)); 

                IntPtr  pIRenderTargetBitmap = IntPtr.Zero; 

                Guid iidRenterTargetBitmap = MILGuidData.IID_IMILRenderTargetBitmap;

                try 
                {
                    // 
                    // We need the render target bitmap. 
                    //
                    HRESULT.Check( 
                        UnsafeNativeMethods.MILUnknown.QueryInterface(
                            _captureRenderTargetBitmap,
                            ref iidRenterTargetBitmap,
                            out pIRenderTargetBitmap)); 

                    // 
                    // Render the frame. 
                    //
                    RenderFrame(pIRenderTargetBitmap, width, height); 
                }
                finally
                {
                    UnsafeNativeMethods.MILUnknown.ReleaseInterface(ref pIRenderTargetBitmap); 
                }
            } 
        } 

 
        /// 
        /// Renders the frame
        /// 
        ///  
        /// Critical - access critical resource (_nativeMedia and renderTargetBitmap)
        ///  
        [SecurityCritical] 
        private
        void 
        RenderFrame(
            IntPtr              pIRenderTargetBitmap,
            uint                width,
            uint                height 
            )
        { 
            DUCE.Resource target = new DUCE.Resource(); 

            DUCE.Resource mediaPlayer = new DUCE.Resource(); 

            DUCE.Resource renderData = new DUCE.Resource();

            DUCE.Resource root = new DUCE.Resource(); 

            try 
            { 
                //
                // Create the root handle first. 
                //
                target.CreateOrAddRefOnChannel(_captureChannel, DUCE.ResourceType.TYPE_GENERICRENDERTARGET);

                mediaPlayer.CreateOrAddRefOnChannel(_captureChannel, DUCE.ResourceType.TYPE_MEDIAPLAYER); 

                renderData.CreateOrAddRefOnChannel(_captureChannel, DUCE.ResourceType.TYPE_RENDERDATA); 
 
                root.CreateOrAddRefOnChannel(_captureChannel, DUCE.ResourceType.TYPE_VISUAL);
 
                //
                // Initialize our render target.
                //
                DUCE.CompositionTarget.PrintInitialize( 
                    target.Handle,
                    pIRenderTargetBitmap, 
                    (int)width, 
                    (int)height,
                    _captureChannel); 

                //
                // Create the synchronous video slave resource.
                // 
                SendMediaPlayerCommand(
                    _captureChannel, 
                    mediaPlayer.Handle, 
                    false,      // Don't notify the Uce directly
                    false);     // player is not remote. 

                //
                // Construct the render data command and serialize it to the composition engine.
                // 
                unsafe
                { 
                    // 
                    // Set the visual as the root for this generic render target.
                    // 
                    DUCE.CompositionTarget.SetRoot(
                        target.Handle,
                        root.Handle,
                        _captureChannel); 

                    uint cbData = (uint)(sizeof(RenderData.RecordHeader) + sizeof(MILCMD_DRAW_VIDEO)); 
 
                    DUCE.MILCMD_RENDERDATA  renderDataCmd;
 
                    renderDataCmd.Type = MILCMD.MilCmdRenderData;
                    renderDataCmd.Handle = renderData.Handle;
                    renderDataCmd.cbData = cbData;
 
                    _captureChannel.BeginCommand(
                        (byte*)&renderDataCmd, 
                        sizeof(DUCE.MILCMD_RENDERDATA), 
                        (int)cbData);
 
                    RenderData.RecordHeader recordHeader;

                    recordHeader.Size = (int)cbData;
                    recordHeader.Id = MILCMD.MilDrawVideo; 

                    _captureChannel.AppendCommandData((byte *)&recordHeader, sizeof(RenderData.RecordHeader)); 
 
                    //
                    // Provide the render data for the DrawVideo call. 
                    //
                    MILCMD_DRAW_VIDEO drawVideo
                        = new MILCMD_DRAW_VIDEO(
                                (uint)mediaPlayer.Handle, 
                                new Rect(0, 0, width, height));
 
                    // 
                    // Send the command to draw the video.
                    // 
                    _captureChannel.AppendCommandData((byte *)&drawVideo, sizeof(MILCMD_DRAW_VIDEO));

                    _captureChannel.EndCommand();
 
                    //
                    // Set the content of this composition node to be the render data. 
                    // 
                    DUCE.CompositionNode.SetContent(
                        root.Handle, 
                        renderData.Handle,
                        _captureChannel);
                }
 
                //
                // Commit the visual and render data down the capture channel. 
                // 
                _captureChannel.Commit();
 
                //
                // Present on the capture channel, this is so we can start getting
                // frame updates.
                // 
                _captureChannel.Present();
 
                _mediaContext.NotifySyncChannelMessage(_captureChannel); 
            }
            finally 
            {
                _renderTargetRoot = root;
            }
        } 

        ///  
        /// Captures the frame that has been rendered by 
        /// 
        ///  
        /// Critical - calls native code, accesses _captureRenderTargetBitmap.
        /// TreatAsSafe - code just retrieves bitmap which could be done through any
        ///               renderTargetBitmap.
        ///  
        [SecurityCritical, SecurityTreatAsSafe]
        private 
        void 
        CaptureFrame()
        { 
            //
            // Now get the bitmap source from the render target.
            //
            BitmapSourceSafeMILHandle   bitmapSource = null; 

            HRESULT.Check( 
                MILRenderTargetBitmap.GetBitmap( 
                    _captureRenderTargetBitmap,
                    out bitmapSource)); 

            //
            // Clear the old bitmao source.
            // 
            ClearBitmapSource();
 
            // 
            // This becomes our new bitmap source, when the resource on the main channel
            // is updated, 
            //
            _bitmapSource = bitmapSource;
        }
 
        #endregion
 
        #region Event Handlers 

        ///  
        /// When a new frame is received, we need to check if it is remote and then acquire the new frame
        /// from the composition synchronously before passing the NewFrame event up to the
        /// Media player.
        ///  
        private
        void 
        OnNewFrame( 
            object          sender,
            EventArgs       args 
            )
        {
            if (_isRemote && HasNonEmptyVideo)
            { 
                OpenCaptureResources();
 
                // 
                // Create synchronous channel here and a RT bitmap, to capture the frame.
                // 
                CaptureFrame();
            }

            _newFrameHelper.InvokeEvents(sender, args); 
        }
 
        ///  
        /// Fired when the media is opened, we can't open our capture resources until the media is opened
        /// because we won't know the size of the media. 
        /// 
        private
        void
        OnMediaOpened( 
            object          sender,
            EventArgs       args 
            ) 
        {
            // 
            // If this is on a remote channel, we need to open the capture resources.
            //
            if (_isRemote && HasNonEmptyVideo)
            { 
                OpenCaptureResources();
            } 
 
            _mediaOpenedHelper.InvokeEvents(sender, args);
        } 

        #endregion

 
        #region Data Members
 
        ///  
        /// Current volume (ranges from 0 to 1)
        ///  
        private double _volume;

        /// 
        /// Current balance (ranges from -1 (left) to 1 (right) ) 
        /// 
        private double _balance; 
 
        /// 
        /// Current state of mute 
        /// 
        private bool _muted;

        ///  
        /// Whether or not scrubbin is enabled
        ///  
        private bool _scrubbingEnabled; 

        ///  
        /// Unamanaged Media object
        /// 
        /// 
        /// Critical - this is a pointer to an unmanaged object that methods are called directly on 
        /// 
        [SecurityCritical] 
        private SafeMediaHandle _nativeMedia; 

        private MediaEventsHelper _mediaEventsHelper; 

        /// 
        /// Default volume
        ///  
        private const double DEFAULT_VOLUME = 0.5;
 
        ///  
        /// Default balance
        ///  
        private const double DEFAULT_BALANCE = 0;

        private double _speedRatio;
        private bool _paused; 

        private Uri _sourceUri; 
 
        private MediaClock _mediaClock = null;
 
        private Dispatcher _dispatcher = null;

        private BitmapSourceSafeMILHandle _bitmapSource;
 
        private DUCE.MultiChannelResource _bitmapSourceDuceHandle;
 
        private bool _isRemote; 

        // 
        // The channel and render data we use to capture the frames.
        //
        DUCE.Channel    _captureChannel;
        MediaContext    _mediaContext; 
        DUCE.Resource   _renderTargetRoot;
 
        ///  
        /// _captureRenderTargetBitmap should be marked as SecurityCritical,
        /// since it's been obtained under elevation, and if disclosed, could 
        /// allow rendering on elements untrusted parties shouldn't be alloowed.
        /// 
        [SecurityCritical]
        SafeMILHandle   _captureRenderTargetBitmap; 

        private UniqueEventHelper _newFrameHelper = new UniqueEventHelper(); 
        private UniqueEventHelper _mediaOpenedHelper = new UniqueEventHelper(); 

        private const float _defaultDevicePixelsPerInch = 96.0F; 

        /// 
        /// A separate class is needed to register for the ProcessExit event
        /// because MediaPlayerState holds a strong reference to _nativeMedia. 
        /// If a MediaPlayerState method was registered for the ProcessExit
        /// event then MediaPlayerState would not be garbage collected until 
        /// ProcessExit time. 
        /// 
        private class Helper 
        {
            /// 
            /// Critical - this is a weak reference to a pointer to an unmanaged object
            /// on which methods are called directly 
            /// 
            [SecurityCritical] 
            private WeakReference _nativeMedia; 

            ///  
            /// Accesses weak reference to pointer
            /// 
            [SecurityCritical]
            internal 
            Helper(
                SafeMediaHandle nativeMedia 
                ) 
            {
                _nativeMedia = new WeakReference(nativeMedia); 
            }

            /// 
            /// Accesses weak reference to pointer, calls unmanaged code 
            /// 
            [SecurityCritical] 
            internal 
            void
            ProcessExitHandler( 
                object sender,
                EventArgs args
                )
            { 
                SafeMediaHandle nativeMedia = (SafeMediaHandle)_nativeMedia.Target;
                if (nativeMedia != null) 
                { 
                    MILMedia.ProcessExitHandler(nativeMedia);
                } 
            }
        };
        #endregion
    } 

    #endregion 
}; 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK