/// <summary>
        /// Process skeleton data associated with an AllFramesReady event.
        /// </summary>
        /// <param name="skeletons">
        /// Skeletons to process.
        /// </param>
        /// <param name="e">
        /// Event arguments.
        /// </param>
        private void ProcessSkeletons(Skeleton[] skeletons, AllFramesReadyEventArgs e)
        {
            IEnumerable <Skeleton> filteredSkeletons = skeletons;

            if (null != SkeletonFilter)
            {
                filteredSkeletons = SkeletonFilter.Filter(skeletons).ToList();
                ChooseSkeletons(filteredSkeletons);
            }

            var idsSeen = new HashSet <int>();

            foreach (Skeleton skeleton in filteredSkeletons)
            {
                if (SkeletonTrackingState.Tracked == skeleton.TrackingState)
                {
                    TPlayer player;

                    // Determine if we're already tracking this player
                    if (id2PlayerMap.ContainsKey(skeleton.TrackingId))
                    {
                        player = id2PlayerMap[skeleton.TrackingId];
                    }
                    else
                    {
                        // If we're not yet tracking player, create one and let client know that
                        // a new player has started interacting with Kinect sensor.
                        player = playerFactory.Create();

                        id2PlayerMap.Add(skeleton.TrackingId, player);

                        OnPlayerStatusChanged(PlayerStatus.Joined, player);
                    }

                    // Update player data and let client know that player has been changed
                    player.Update(skeleton, e);

                    OnPlayerStatusChanged(PlayerStatus.Updated, player);

                    idsSeen.Add(skeleton.TrackingId);
                }
            }

            // Check if any players have left the scene
            var leftScene = new HashSet <int>();

            foreach (int tracked in id2PlayerMap.Keys)
            {
                if (!idsSeen.Contains(tracked))
                {
                    leftScene.Add(tracked);
                }
            }

            // Let client know if any players have stopped interacting with Kinect sensor
            foreach (int id in leftScene)
            {
                var leavingPlayer = id2PlayerMap[id];
                OnPlayerStatusChanged(PlayerStatus.Left, leavingPlayer);
                id2PlayerMap.Remove(id);
                playerFactory.Cleanup(leavingPlayer);
            }
        }