/// <summary>
        /// Initialize the media element for playback
        /// </summary>
        /// <param name="streamConfig">Object containing stream configuration details</param>
        void InitializeMediaPlayer(MoonlightStreamConfiguration streamConfig, AvStreamSource streamSource)
        {
            this._streamSource = streamSource;

            // This code is based upon the MS FFmpegInterop project on GitHub
            VideoEncodingProperties videoProps = VideoEncodingProperties.CreateH264();

            videoProps.ProfileId = H264ProfileIds.High;
            videoProps.Width     = (uint)streamConfig.GetWidth();
            videoProps.Height    = (uint)streamConfig.GetHeight();
            videoProps.Bitrate   = (uint)streamConfig.GetBitrate();

            _videoMss                  = new MediaStreamSource(new VideoStreamDescriptor(videoProps));
            _videoMss.BufferTime       = TimeSpan.Zero;
            _videoMss.CanSeek          = false;
            _videoMss.Duration         = TimeSpan.Zero;
            _videoMss.SampleRequested += _videoMss_SampleRequested;

            XAudio2        xaudio         = new XAudio2();
            MasteringVoice masteringVoice = new MasteringVoice(xaudio, 2, 48000);
            WaveFormat     format         = new WaveFormat(48000, 16, 2);

            // Set for low latency playback
            StreamDisplay.RealTimePlayback = true;

            // Render on the full window to avoid extra compositing
            StreamDisplay.IsFullWindow = true;

            // Disable built-in transport controls
            StreamDisplay.AreTransportControlsEnabled = false;

            StreamDisplay.SetMediaStreamSource(_videoMss);
            AvStream.SetSourceVoice(new SourceVoice(xaudio, format));
        }
        /// <summary>
        /// When the user presses "Start Streaming Steam", first check that they are paired
        /// </summary>
        public static async Task<StreamContext> StartStreaming(CoreDispatcher uiDispatcher, Computer computer, MoonlightStreamConfiguration streamConfig)
        {
            PairingManager p = new PairingManager(computer); 

            // If we can't get the pair state, return   
            bool? pairState = await p.QueryPairState();
            if (!pairState.HasValue)
            {
                DialogUtils.DisplayDialog(uiDispatcher, "Pair state query failed", "Failed to start streaming");
                return null;
            }

            // If we're not paired, return
            if (pairState == false)
            {
                DialogUtils.DisplayDialog(uiDispatcher, "Device not paired", "Failed to start streaming");
                return null;
            }

            // Lookup the desired app in the app list
            // NOTE: This will go away when we have a proper app list
            int appId = await LookupAppIdForApp(uiDispatcher, new NvHttp(computer.IpAddress), "Steam");
            if (appId == 0)
            {
                // LookupAppIdForApp() handles displaying a failure dialog
                return null;
            }

            return new StreamContext(computer, appId, streamConfig);
        }
示例#3
0
        /// <summary>
        /// Initialize the media element for playback
        /// </summary>
        /// <param name="streamConfig">Object containing stream configuration details</param>
        void InitializeMediaPlayer(MoonlightStreamConfiguration streamConfig, AvStreamSource streamSource)
        {
            this._streamSource = streamSource;

            _videoMss = new MediaStreamSource(new VideoStreamDescriptor(VideoEncodingProperties.CreateH264()));
            _videoMss.BufferTime = TimeSpan.Zero;
            _videoMss.CanSeek = false;
            _videoMss.Duration = TimeSpan.Zero;
            _videoMss.SampleRequested += _videoMss_SampleRequested;

            XAudio2 xaudio = new XAudio2();
            MasteringVoice masteringVoice = new MasteringVoice(xaudio, 2, 48000);
            WaveFormat format = new WaveFormat(48000, 16, 2);

            // Set for low latency playback
            StreamDisplay.RealTimePlayback = true;

            // Render on the full window to avoid extra compositing
            StreamDisplay.IsFullWindow = true;

            // Disable built-in transport controls
            StreamDisplay.AreTransportControlsEnabled = false;

            // Start playing right away
            StreamDisplay.AutoPlay = true;

            StreamDisplay.SetMediaStreamSource(_videoMss);

            AvStream.SetSourceVoice(new SourceVoice(xaudio, format));
        }
示例#4
0
        /// <summary>
        /// Starts the connection by calling into Moonlight Common
        /// </summary>
        private async Task StartConnection(MoonlightStreamConfiguration streamConfig)
        {
            NvHttp nv = null;
            await SetStateText("Resolving hostname...");
            try
            {
                nv = new NvHttp(context.computer.IpAddress);
            }
            catch (ArgumentNullException)
            {
                stageFailureText = "Error resolving hostname";
                ConnectionFailed();
                return;
            }

            String serverIp = null;
            try
            {
                serverIp = await nv.ResolveServerIPAddress();
            }
            catch (Exception)
            {
                stageFailureText = "Error resolving hostname";
                ConnectionFailed();
                return;
            }

            // Set up callbacks
            MoonlightDecoderRenderer drCallbacks = new MoonlightDecoderRenderer(DrSetup, DrCleanup, DrSubmitDecodeUnit);
            MoonlightAudioRenderer arCallbacks = new MoonlightAudioRenderer(ArInit, ArCleanup, ArPlaySample);
            MoonlightConnectionListener clCallbacks = new MoonlightConnectionListener(ClStageStarting, ClStageComplete, ClStageFailed,
            ClConnectionStarted, ClConnectionTerminated, ClDisplayMessage, ClDisplayTransientMessage);

            // Launch Steam
            await SetStateText("Launching Steam");
            if (await StartOrResumeApp(nv, streamConfig) == false)
            {
                Debug.WriteLine("Can't find app");
                stageFailureText = "Error launching App";
                ConnectionFailed();
                return;
            }

            // Call into Common to start the connection
            Debug.WriteLine("Starting connection");

            MoonlightCommonRuntimeComponent.StartConnection(serverIp, streamConfig, clCallbacks, drCallbacks, arCallbacks, serverMajorVersion);

            if (stageFailureText != null)
            {
                Debug.WriteLine("Stage failed");
                ConnectionFailed();
                return;
            }
            else
            {
                ConnectionSuccess();
            }
        }
示例#5
0
        /// <summary>
        /// Create start HTTP request
        /// </summary>
        private async Task<bool> StartOrResumeApp(NvHttp nv, MoonlightStreamConfiguration streamConfig)
        {
            XmlQuery serverInfo = new XmlQuery(nv.BaseUrl + "/serverinfo?uniqueid=" + nv.GetUniqueId());
            string currentGameString = await serverInfo.ReadXmlElement("currentgame");
            if (currentGameString == null)
            {
                return false;
            }

            string versionString = await serverInfo.ReadXmlElement("appversion");
            if (versionString == null)
            {
                return false;
            }

            serverMajorVersion = Convert.ToInt32(versionString.Substring(0, 1));

            byte[] aesIv = streamConfig.GetRiAesIv();
            int riKeyId =
                (int)(((aesIv[0] << 24) & 0xFF000000U) |
                ((aesIv[1] << 16) & 0xFF0000U) |
                ((aesIv[2] << 8) & 0xFF00U) |
                (aesIv[3] & 0xFFU));
            string riConfigString =
                "&rikey=" + PairingCryptoHelpers.BytesToHex(streamConfig.GetRiAesKey()) +
                "&rikeyid=" + riKeyId;

            // Launch a new game if nothing is running
            if (currentGameString == null || currentGameString.Equals("0"))
            {
                XmlQuery x = new XmlQuery(nv.BaseUrl + "/launch?uniqueid=" + nv.GetUniqueId() + "&appid=" + context.appId +
                    "&mode=" + streamConfig.GetWidth() + "x" + streamConfig.GetHeight() + "x" + streamConfig.GetFps() +
                    "&additionalStates=1&sops=1" + // FIXME: make sops configurable
                    riConfigString);

                string sessionStr = await x.ReadXmlElement("gamesession");
                if (sessionStr == null || sessionStr.Equals("0"))
                {
                    return false;
                }

                return true;
            }
            else
            {
                // A game was already running, so resume it
                // FIXME: Quit and relaunch if it's not the game we came to start
                XmlQuery x = new XmlQuery(nv.BaseUrl + "/resume?uniqueid=" + nv.GetUniqueId() + riConfigString);

                string resumeStr = await x.ReadXmlElement("resume");
                if (resumeStr == null || resumeStr.Equals("0"))
                {
                    return false;
                }

                return true;
            }
        }
示例#6
0
        /// <summary>
        /// Executed when the user presses "Start Streaming Steam!"
        /// </summary>
        private async Task StreamButton_Click_Common()
        {
            Debug.WriteLine("Start Streaming button pressed");

            selected = (Computer)computerPicker.SelectedItem;

            // User hasn't selected a machine or selected a placeholder
            if (selected == null || String.IsNullOrWhiteSpace(selected.IpAddress))
            {
                DialogUtils.DisplayDialog(this.Dispatcher, "No machine selected", "Streaming Failed");
            }
            else
            {
                // Stop enumerating machines while we're trying to check pair state
                mDnsTimer.Stop();

                byte[] aesKey = PairingCryptoHelpers.GenerateRandomBytes(16);

                // GameStream only uses 4 bytes of a 16 byte IV. Go figure.
                byte[] aesRiIndex = PairingCryptoHelpers.GenerateRandomBytes(4);
                byte[] aesIv      = new byte[16];
                Array.ConstrainedCopy(aesRiIndex, 0, aesIv, 0, aesRiIndex.Length);
                SettingsPage s = new SettingsPage();
                MoonlightStreamConfiguration config = new MoonlightStreamConfiguration(
                    s.GetStreamWidth(),
                    s.GetStreamHeight(),
                    s.GetStreamFps(),
                    10000, // FIXME: Scale by resolution
                    1024,
                    aesKey, aesIv);

                StreamContext context = await ConnectionManager.StartStreaming(this.Dispatcher, selected, config);

                if (context != null)
                {
                    this.Frame.Navigate(typeof(StreamFrame), context);
                }
            }
        }
        /// <summary>
        /// When the user presses "Start Streaming Steam", first check that they are paired
        /// </summary>
        public static async Task <StreamContext> StartStreaming(CoreDispatcher uiDispatcher, Computer computer, MoonlightStreamConfiguration streamConfig)
        {
            PairingManager p = new PairingManager(computer);

            // If we can't get the pair state, return
            bool?pairState = await p.QueryPairState();

            if (!pairState.HasValue)
            {
                DialogUtils.DisplayDialog(uiDispatcher, "Pair state query failed", "Failed to start streaming");
                return(null);
            }

            // If we're not paired, return
            if (pairState == false)
            {
                DialogUtils.DisplayDialog(uiDispatcher, "Device not paired", "Failed to start streaming");
                return(null);
            }

            // Lookup the desired app in the app list
            // NOTE: This will go away when we have a proper app list
            int appId = await LookupAppIdForApp(uiDispatcher, new NvHttp(computer.IpAddress), "Steam");

            if (appId == 0)
            {
                // LookupAppIdForApp() handles displaying a failure dialog
                return(null);
            }

            return(new StreamContext(computer, appId, streamConfig));
        }
 public StreamContext(Computer computer, int appId, MoonlightStreamConfiguration streamConfig)
 {
     this.computer = computer;
     this.appId = appId;
     this.streamConfig = streamConfig;
 }
 public StreamContext(Computer computer, int appId, MoonlightStreamConfiguration streamConfig)
 {
     this.computer     = computer;
     this.appId        = appId;
     this.streamConfig = streamConfig;
 }
        /// <summary>
        /// Executed when the user presses "Start Streaming Steam!"
        /// </summary>
        private async Task StreamButton_Click_Common()
        {
            Debug.WriteLine("Start Streaming button pressed");

            selected = (Computer)computerPicker.SelectedItem;

            // User hasn't selected a machine or selected a placeholder
            if (selected == null || String.IsNullOrWhiteSpace(selected.IpAddress))
            {
                DialogUtils.DisplayDialog(this.Dispatcher, "No machine selected", "Streaming Failed");
            }
            else
            {
                // Stop enumerating machines while we're trying to check pair state
                mDnsTimer.Stop();

                byte[] aesKey = PairingCryptoHelpers.GenerateRandomBytes(16);

                // GameStream only uses 4 bytes of a 16 byte IV. Go figure.
                byte[] aesRiIndex = PairingCryptoHelpers.GenerateRandomBytes(4);
                byte[] aesIv = new byte[16];
                Array.ConstrainedCopy(aesRiIndex, 0, aesIv, 0, aesRiIndex.Length);
                SettingsPage s = new SettingsPage();
                MoonlightStreamConfiguration config = new MoonlightStreamConfiguration(
                    s.GetStreamWidth(),
                    s.GetStreamHeight(),
                    s.GetStreamFps(),
                    10000, // FIXME: Scale by resolution
                    1024,
                    aesKey, aesIv);

                StreamContext context = await ConnectionManager.StartStreaming(this.Dispatcher, selected, config);
                if (context != null)
                {
                    this.Frame.Navigate(typeof(StreamFrame), context);
                }
            }
        }
示例#11
0
        /// <summary>
        /// Starts the connection by calling into Moonlight Common
        /// </summary>
        private async Task StartConnection(MoonlightStreamConfiguration streamConfig)
        {
            NvHttp nv = null;

            await SetStateText("Resolving hostname...");

            try
            {
                nv = new NvHttp(context.computer.IpAddress);
            }
            catch (ArgumentNullException)
            {
                stageFailureText = "Error resolving hostname";
                ConnectionFailed();
                return;
            }

            String serverIp = null;

            try
            {
                serverIp = await nv.ResolveServerIPAddress();
            }
            catch (Exception)
            {
                stageFailureText = "Error resolving hostname";
                ConnectionFailed();
                return;
            }

            // Set up callbacks
            MoonlightDecoderRenderer    drCallbacks = new MoonlightDecoderRenderer(DrSetup, DrCleanup, DrSubmitDecodeUnit);
            MoonlightAudioRenderer      arCallbacks = new MoonlightAudioRenderer(ArInit, ArCleanup, ArPlaySample);
            MoonlightConnectionListener clCallbacks = new MoonlightConnectionListener(ClStageStarting, ClStageComplete, ClStageFailed,
                                                                                      ClConnectionStarted, ClConnectionTerminated, ClDisplayMessage, ClDisplayTransientMessage);

            // Launch Steam
            await SetStateText("Launching Steam");

            if (await StartOrResumeApp(nv, streamConfig) == false)
            {
                Debug.WriteLine("Can't find app");
                stageFailureText = "Error launching App";
                ConnectionFailed();
                return;
            }

            // Call into Common to start the connection
            Debug.WriteLine("Starting connection");

            MoonlightCommonRuntimeComponent.StartConnection(serverIp, streamConfig, clCallbacks, drCallbacks, arCallbacks, serverMajorVersion);

            if (stageFailureText != null)
            {
                Debug.WriteLine("Stage failed");
                ConnectionFailed();
                return;
            }
            else
            {
                ConnectionSuccess();
            }
        }
示例#12
0
        /// <summary>
        /// Create start HTTP request
        /// </summary>
        private async Task <bool> StartOrResumeApp(NvHttp nv, MoonlightStreamConfiguration streamConfig)
        {
            XmlQuery serverInfo        = new XmlQuery(nv.BaseUrl + "/serverinfo?uniqueid=" + nv.GetUniqueId());
            string   currentGameString = await serverInfo.ReadXmlElement("currentgame");

            if (currentGameString == null)
            {
                return(false);
            }

            string versionString = await serverInfo.ReadXmlElement("appversion");

            if (versionString == null)
            {
                return(false);
            }

            serverMajorVersion = Convert.ToInt32(versionString.Substring(0, 1));

            byte[] aesIv   = streamConfig.GetRiAesIv();
            int    riKeyId =
                (int)(((aesIv[0] << 24) & 0xFF000000U) |
                      ((aesIv[1] << 16) & 0xFF0000U) |
                      ((aesIv[2] << 8) & 0xFF00U) |
                      (aesIv[3] & 0xFFU));
            string riConfigString =
                "&rikey=" + PairingCryptoHelpers.BytesToHex(streamConfig.GetRiAesKey()) +
                "&rikeyid=" + riKeyId;

            // Launch a new game if nothing is running
            if (currentGameString == null || currentGameString.Equals("0"))
            {
                XmlQuery x = new XmlQuery(nv.BaseUrl + "/launch?uniqueid=" + nv.GetUniqueId() + "&appid=" + context.appId +
                                          "&mode=" + streamConfig.GetWidth() + "x" + streamConfig.GetHeight() + "x" + streamConfig.GetFps() +
                                          "&additionalStates=1&sops=1" + // FIXME: make sops configurable
                                          riConfigString);

                string sessionStr = await x.ReadXmlElement("gamesession");

                if (sessionStr == null || sessionStr.Equals("0"))
                {
                    return(false);
                }

                return(true);
            }
            else
            {
                // A game was already running, so resume it
                // FIXME: Quit and relaunch if it's not the game we came to start
                XmlQuery x = new XmlQuery(nv.BaseUrl + "/resume?uniqueid=" + nv.GetUniqueId() + riConfigString);

                string resumeStr = await x.ReadXmlElement("resume");

                if (resumeStr == null || resumeStr.Equals("0"))
                {
                    return(false);
                }

                return(true);
            }
        }
示例#13
-1
        /// <summary>
        /// Initialize the media element for playback
        /// </summary>
        /// <param name="streamConfig">Object containing stream configuration details</param>
        void InitializeMediaPlayer(MoonlightStreamConfiguration streamConfig, AvStreamSource streamSource)
        {
            this._streamSource = streamSource;

            // This code is based upon the MS FFmpegInterop project on GitHub
            VideoEncodingProperties videoProps = VideoEncodingProperties.CreateH264();
            videoProps.ProfileId = H264ProfileIds.High;
            videoProps.Width = (uint)streamConfig.GetWidth();
            videoProps.Height = (uint)streamConfig.GetHeight();
            videoProps.Bitrate = (uint)streamConfig.GetBitrate();

            _videoMss = new MediaStreamSource(new VideoStreamDescriptor(videoProps));
            _videoMss.BufferTime = TimeSpan.Zero;
            _videoMss.CanSeek = false;
            _videoMss.Duration = TimeSpan.Zero;
            _videoMss.SampleRequested += _videoMss_SampleRequested;

            XAudio2 xaudio = new XAudio2();
            MasteringVoice masteringVoice = new MasteringVoice(xaudio, 2, 48000);
            WaveFormat format = new WaveFormat(48000, 16, 2);

            // Set for low latency playback
            StreamDisplay.RealTimePlayback = true;

            // Render on the full window to avoid extra compositing
            StreamDisplay.IsFullWindow = true;

            // Disable built-in transport controls
            StreamDisplay.AreTransportControlsEnabled = false;

            StreamDisplay.SetMediaStreamSource(_videoMss);
            AvStream.SetSourceVoice(new SourceVoice(xaudio, format));
        }