示例#1
0
        /// <summary>
        /// Create start HTTP request
        /// </summary>
        private XmlQuery StartOrResumeApp(NvHttp nv, LimelightStreamConfiguration streamConfig)
        {
            XmlQuery serverInfo = new XmlQuery(nv.baseUrl + "/serverinfo?uniqueid=" + nv.GetUniqueId());
            string currentGameString = serverInfo.XmlAttribute("currentgame");

            byte[] aesIv = streamConfig.GetRiAesIv();
            int riKeyId =
                (int)(((aesIv[0] << 24) & 0xFF000000) |
                ((aesIv[1] << 16) & 0xFF0000) |
                ((aesIv[2] << 8) & 0xFF00) |
                (aesIv[3] & 0xFF));
            string riConfigString =
                "&rikey=" + Pairing.bytesToHex(streamConfig.GetRiAesKey()) +
                "&rikeyid=" + riKeyId;

            // Launch a new game if nothing is running
            if (currentGameString == null || currentGameString.Equals("0"))
            {
                return new XmlQuery(nv.baseUrl + "/launch?uniqueid=" + nv.GetUniqueId() + "&appid=" + selected.steamID +
                    "&mode=" + streamConfig.GetWidth() + "x" + streamConfig.GetHeight() + "x" + streamConfig.GetFps() +
                    "&additionalStates=1&sops=1" + // FIXME: make sops configurable
                    riConfigString);
            }
            else
            {
                // A game was already running, so resume it
                // FIXME: Quit and relaunch if it's not the game we came to start
                return new XmlQuery(nv.baseUrl + "/resume?uniqueid=" + nv.GetUniqueId() + riConfigString);
            }
        }
示例#2
0
        /// <summary>
        /// Create start HTTP request
        /// </summary>
        private XmlQuery StartOrResumeApp(NvHttp nv, LimelightStreamConfiguration streamConfig)
        {
            XmlQuery serverInfo        = new XmlQuery(nv.BaseUrl + "/serverinfo?uniqueid=" + nv.GetUniqueId());
            string   currentGameString = serverInfo.XmlAttribute("currentgame");

            byte[] aesIv   = streamConfig.GetRiAesIv();
            int    riKeyId =
                (int)(((aesIv[0] << 24) & 0xFF000000) |
                      ((aesIv[1] << 16) & 0xFF0000) |
                      ((aesIv[2] << 8) & 0xFF00) |
                      (aesIv[3] & 0xFF));
            string riConfigString =
                "&rikey=" + Pairing.bytesToHex(streamConfig.GetRiAesKey()) +
                "&rikeyid=" + riKeyId;

            // Launch a new game if nothing is running
            if (currentGameString == null || currentGameString.Equals("0"))
            {
                return(new XmlQuery(nv.BaseUrl + "/launch?uniqueid=" + nv.GetUniqueId() + "&appid=" + selected.steamID +
                                    "&mode=" + streamConfig.GetWidth() + "x" + streamConfig.GetHeight() + "x" + streamConfig.GetFps() +
                                    "&additionalStates=1&sops=1" + // FIXME: make sops configurable
                                    riConfigString));
            }
            else
            {
                // A game was already running, so resume it
                // FIXME: Quit and relaunch if it's not the game we came to start
                return(new XmlQuery(nv.BaseUrl + "/resume?uniqueid=" + nv.GetUniqueId() + riConfigString));
            }
        }
        /// <summary>
        /// Event handler for page loaded event
        /// </summary>
        private async void Loaded(object sender, RoutedEventArgs e)
        {
            StreamDisplay.Visibility    = Visibility.Visible;
            Waitgrid.Visibility         = Visibility.Collapsed;
            currentStateText.Visibility = Visibility.Collapsed;

            // Hide the status bar
            //var statusBar = Windows.UI.ViewManagement.StatusBar.GetForCurrentView();
            //await statusBar.HideAsync();

            LimelightStreamConfiguration config;

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

            // GameStream only uses 4 bytes of a 16 byte IV. Go figure.
            byte[] aesRiIndex = Pairing.GenerateRandomBytes(4);
            byte[] aesIv      = new byte[16];
            Array.ConstrainedCopy(aesRiIndex, 0, aesIv, 0, aesRiIndex.Length);

            config = new LimelightStreamConfiguration(selected.pixels * (16 / 9), selected.pixels,
                                                      selected.fps, 5000, 1024, aesKey, aesIv);
            InitializeMediaPlayer(config, AvStream);

            //H264FileReaderHackery h = new H264FileReaderHackery();
            //Task.Run(() => h.readFile(this));

            await StartConnection(config);
        }
示例#4
0
        /// <summary>
        /// Starts the connection by calling into Limelight Common
        /// </summary>
        private async Task StartConnection()
        {
            NvHttp nv = null;

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

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

            XmlQuery launchApp;

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

            try
            {
                launchApp = new XmlQuery(nv.baseUrl + "/launch?uniqueid=" + nv.GetDeviceName() + "&appid=" + selected.steamID);
            }
            catch (Exception)
            {
                Debug.WriteLine("Can't find steam");
                stageFailureText = "Error launching Steam";
                ConnectionFailed();
                return;
            }

            // Set up callbacks
            LimelightStreamConfiguration streamConfig = new LimelightStreamConfiguration(frameWidth, frameHeight, 30, 10000, 1024); // TODO a magic number. Get FPS from the settings
            LimelightDecoderRenderer     drCallbacks  = new LimelightDecoderRenderer(DrSetup, DrStart, DrStop, DrRelease, DrSubmitDecodeUnit);
            LimelightAudioRenderer       arCallbacks  = new LimelightAudioRenderer(ArInit, ArStart, ArStop, ArRelease, ArPlaySample);
            LimelightConnectionListener  clCallbacks  = new LimelightConnectionListener(ClStageStarting, ClStageComplete, ClStageFailed,
                                                                                        ClConnectionStarted, ClConnectionTerminated, ClDisplayMessage, ClDisplayTransientMessage);

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

            //uint addr = (uint)nv.resolvedHost.ToString(); // TODO how to get the addr as a uint
            LimelightCommonRuntimeComponent.StartConnection(addr, streamConfig, clCallbacks, drCallbacks, arCallbacks);

            if (stageFailureText != null)
            {
                Debug.WriteLine("Stage failed");
                ConnectionFailed();
                return;
            }
            else
            {
                ConnectionSuccess();
            }
        }
示例#5
0
        /// <summary>
        /// Initialize the media element for playback
        /// </summary>
        /// <param name="streamConfig">Object containing stream configuration details</param>
        void InitializeMediaPlayer(LimelightStreamConfiguration streamConfig, AvStreamSource streamSource)
        {
            this._streamSource = streamSource;

            AudioEncodingProperties audioProperties = AudioEncodingProperties.CreatePcm(48000, 2, 16);

            VideoEncodingProperties videoProperties = VideoEncodingProperties.CreateUncompressed(MediaEncodingSubtypes.H264Es,
                                                                                                 (uint)streamConfig.GetWidth(), (uint)streamConfig.GetHeight());

            videoProperties.ProfileId = H264ProfileIds.High;

            _videoDesc = new VideoStreamDescriptor(videoProperties);
            _audioDesc = new AudioStreamDescriptor(audioProperties);

            _mss                  = new MediaStreamSource(_videoDesc, _audioDesc);
            _mss.BufferTime       = TimeSpan.Zero;
            _mss.CanSeek          = false;
            _mss.Duration         = TimeSpan.Zero;
            _mss.SampleRequested += _mss_SampleRequested;

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

            // Set the audio category to take advantage of hardware audio offload
            StreamDisplay.AudioCategory = AudioCategory.ForegroundOnlyMedia;

            // 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(_mss);
        }
示例#6
0
        /// <summary>
        /// Initialize the media element for playback
        /// </summary>
        /// <param name="streamConfig">Object containing stream configuration details</param>
        void InitializeMediaPlayer(LimelightStreamConfiguration streamConfig, AvStreamSource streamSource)
        {
            this._streamSource = streamSource;

            AudioEncodingProperties audioProperties = AudioEncodingProperties.CreatePcm(48000, 2, 16);

            VideoEncodingProperties videoProperties = VideoEncodingProperties.CreateUncompressed(MediaEncodingSubtypes.H264Es,
                (uint)streamConfig.GetWidth(), (uint)streamConfig.GetHeight());
            videoProperties.ProfileId = H264ProfileIds.High;

            _videoDesc = new VideoStreamDescriptor(videoProperties);
            _audioDesc = new AudioStreamDescriptor(audioProperties);

            _mss = new MediaStreamSource(_videoDesc, _audioDesc);
            _mss.BufferTime = TimeSpan.Zero;
            _mss.CanSeek = false;
            _mss.Duration = TimeSpan.Zero;
            _mss.SampleRequested += _mss_SampleRequested;

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

            // Set the audio category to take advantage of hardware audio offload
            StreamDisplay.AudioCategory = AudioCategory.ForegroundOnlyMedia;

            // 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(_mss);
        }
示例#7
0
        /// <summary>
        /// Starts the connection by calling into Limelight Common
        /// </summary>
        private async Task StartConnection(LimelightStreamConfiguration streamConfig)
        {
            NvHttp nv = null;
            await SetStateText("Resolving hostname...");
            try
            {
                nv = new NvHttp(selected.IpAddress);
            }
            catch (ArgumentNullException)
            {
                stageFailureText = "Error resolving hostname";
                ConnectionFailed();
                return;
            }

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

            // Set up callbacks
            LimelightDecoderRenderer drCallbacks = new LimelightDecoderRenderer(DrSetup, DrStart, DrStop, DrRelease, DrSubmitDecodeUnit);
            LimelightAudioRenderer arCallbacks = new LimelightAudioRenderer(ArInit, ArStart, ArStop, ArRelease, ArPlaySample);
            LimelightConnectionListener clCallbacks = new LimelightConnectionListener(ClStageStarting, ClStageComplete, ClStageFailed,
            ClConnectionStarted, ClConnectionTerminated, ClDisplayMessage, ClDisplayTransientMessage);

            XmlQuery launchApp;
            // Launch Steam
            await SetStateText("Launching Steam");
            try
            {
                launchApp = StartOrResumeApp(nv, streamConfig);
            }
            catch (Exception)
            {
                Debug.WriteLine("Can't find steam");
                stageFailureText = "Error launching Steam";
                ConnectionFailed();
                return;
            }

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

            Regex r = new Regex(@"^(?<octet1>\d+).(?<octet2>\d+).(?<octet3>\d+).(?<octet4>\d+)");
            Match m = r.Match(selected.IpAddress);

            uint addr = (uint)(Convert.ToByte(m.Groups["octet4"].Value) << 24 |
                Convert.ToByte(m.Groups["octet3"].Value) << 16 | 
                Convert.ToByte(m.Groups["octet2"].Value) << 8 |
                Convert.ToByte(m.Groups["octet1"].Value));
            LimelightCommonRuntimeComponent.StartConnection(addr, streamConfig, clCallbacks, drCallbacks, arCallbacks);

            if (stageFailureText != null)
            {
                Debug.WriteLine("Stage failed");
                ConnectionFailed();
                return;
            }
            else
            {
                ConnectionSuccess();
            }
        }
示例#8
0
        /// <summary>
        /// Starts the connection by calling into Limelight Common
        /// </summary>
        private async Task StartConnection(LimelightStreamConfiguration streamConfig)
        {
            NvHttp nv = null;

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

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

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

            // Set up callbacks
            LimelightDecoderRenderer    drCallbacks = new LimelightDecoderRenderer(DrSetup, DrStart, DrStop, DrRelease, DrSubmitDecodeUnit);
            LimelightAudioRenderer      arCallbacks = new LimelightAudioRenderer(ArInit, ArStart, ArStop, ArRelease, ArPlaySample);
            LimelightConnectionListener clCallbacks = new LimelightConnectionListener(ClStageStarting, ClStageComplete, ClStageFailed,
                                                                                      ClConnectionStarted, ClConnectionTerminated, ClDisplayMessage, ClDisplayTransientMessage);

            XmlQuery launchApp;

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

            try
            {
                launchApp = StartOrResumeApp(nv, streamConfig);
            }
            catch (Exception)
            {
                Debug.WriteLine("Can't find steam");
                stageFailureText = "Error launching Steam";
                ConnectionFailed();
                return;
            }

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

            Regex r = new Regex(@"^(?<octet1>\d+).(?<octet2>\d+).(?<octet3>\d+).(?<octet4>\d+)");
            Match m = r.Match(selected.IpAddress);

            uint addr = (uint)(Convert.ToByte(m.Groups["octet4"].Value) << 24 |
                               Convert.ToByte(m.Groups["octet3"].Value) << 16 |
                               Convert.ToByte(m.Groups["octet2"].Value) << 8 |
                               Convert.ToByte(m.Groups["octet1"].Value));

            LimelightCommonRuntimeComponent.StartConnection(addr, streamConfig, clCallbacks, drCallbacks, arCallbacks);

            if (stageFailureText != null)
            {
                Debug.WriteLine("Stage failed");
                ConnectionFailed();
                return;
            }
            else
            {
                ConnectionSuccess();
            }
        }
        /// <summary>
        /// Event handler for Background Worker's doWork event.
        /// </summary>
        private void bwDoWork(object sender, DoWorkEventArgs e)
        {
            Debug.WriteLine("Doing work");
            String hostNameString = (String)PhoneApplicationService.Current.State["host"];
            // Resolve the host name to an IP address string.
            Dispatcher.BeginInvoke(new Action(() => setStateText("Resolving hostname...")));
            ResolveHostName(hostNameString);
            stopWaitHandle.WaitOne();

            // Set up callbacks
            LimelightStreamConfiguration streamConfig = new LimelightStreamConfiguration(frameWidth, frameHeight, 30); // TODO a magic number. Get FPS from the settings
            LimelightDecoderRenderer drCallbacks = new LimelightDecoderRenderer(DrSetup, DrStart, DrStop, DrRelease, DrSubmitDecodeUnit);
            LimelightAudioRenderer arCallbacks = new LimelightAudioRenderer(ArInit, ArStart, ArStop, ArRelease, ArPlaySample);
            LimelightConnectionListener clCallbacks = new LimelightConnectionListener(ClStageStarting, ClStageComplete, ClStageFailed,
            ClConnectionStarted, ClConnectionTerminated, ClDisplayMessage, ClDisplayTransientMessage);

            // Call into Common to start the connection
            Debug.WriteLine("Starting connection");
            LimelightCommonRuntimeComponent.StartConnection((uint)resolvedHost.Address, streamConfig, clCallbacks, drCallbacks, arCallbacks);

            // If one of the stages failed, tell the background worker to cancel
            if(stageFailureText != null)
            {
                Debug.WriteLine("Stage failed - background worker cancelled");
                e.Cancel = true;
            }
        }
示例#10
0
        /// <summary>
        /// Event handler for page loaded event
        /// </summary>
        private async void Loaded(object sender, RoutedEventArgs e)
        {
            StreamDisplay.Visibility = Visibility.Visible;
            Waitgrid.Visibility = Visibility.Collapsed;
            currentStateText.Visibility = Visibility.Collapsed;
            
            // Hide the status bar
            //var statusBar = Windows.UI.ViewManagement.StatusBar.GetForCurrentView();
            //await statusBar.HideAsync(); 
            
            LimelightStreamConfiguration config;

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

            // GameStream only uses 4 bytes of a 16 byte IV. Go figure.
            byte[] aesRiIndex = Pairing.GenerateRandomBytes(4);
            byte[] aesIv = new byte[16];
            Array.ConstrainedCopy(aesRiIndex, 0, aesIv, 0, aesRiIndex.Length);
 
            config = new LimelightStreamConfiguration(selected.pixels*(16/9), selected.pixels,
                selected.fps, 5000, 1024, aesKey, aesIv);
            InitializeMediaPlayer(config, AvStream);

            //H264FileReaderHackery h = new H264FileReaderHackery();
            //Task.Run(() => h.readFile(this));

            await StartConnection(config);
        }