As I mentioned in my previous post, at this year’s Microsoft Community Bootcamp I entered in the demo competition together with Adi. We’ve had some issues in the past with (cheap) broadcasting of presentations. There are plenty of professional tools out there that accomplish this goal, but that’s not my point. My point is that I have not yet found a cheap (free) utility that will allow me to give a presentation to several viewers that may not be in the same room (or the screen isn’t big enough for the whole audience).
Given this background, Adi proposed we create a way in which several people can see the same thing that a broadcaster transmits. Further, the “thing” that everyone sees is actually an XNA game, that could might as well be an interactive presentation in 3D.
The main idea is that, given an XNA game (possibly a game that did not take into consideration broadcasting though our “system”), produce a mechanism such that a broadcaster can transmit the content on the screen to any number of observers. As infrastructure for communication a WCF service was chosen. The reason for this is because it is relatively quick to implement and set up, it supports binary protocols and also bidirectional, asynchronous communication via service callbacks.
The first idea that comes to mind when deciding what to broadcast is whole images, pixel by pixel. The trouble with this is that if we have an application with resolution of 800×600 pixels, 32 bit color depth, at 60 frames/second, then we would require at least 109 MBytes/second/observer. This is totally unacceptable. Even with video compression, it would still require substantial bandwidth.
Instead, we decided that we could reduce the whole state of a game to a few state variables and a few “laws” that govern how these state variables evolve in time. Transmitting only some state variables proves to require much less bandwidth than transmitting the whole image. To further reduce the size of the messages transmitted, we identified 2 categories of state variables: the ones that are directly influenced by a user (through keyboard input for example), and the ones that have an initial value, and a law that dictates it’s evolution in time. The state variables that evolve independent of user input can be left out of the “frame-by-frame” transmissions, and just the initial value has to be transmitted.
XNA Streaming Components
Given the initial description of the system proposed, we decided initially on three components:
The Streaming Service, that would receive calls from the broadcaster when state variables change and then transmit those changes through callbacks to all the subscribed observers. Aside from this main communication channel, the Streaming Service also provides initial synchronization for observers, meaning the service prompts the broadcaster (through a callback) to send the whole game state each time a new observer connects.
The File Transfer Service is responsible for storing all “broadcastable” game binaries, delivering them to clients and providing startup information for each game (Streaming Service address).
The actual game, which has to be able to run in two modes: broadcast and observer. The game makes service calls to transmit/request state variables and responds to the callbacks of the Streaming Service.
At this point we analysed the communication between the game and the Streaming Service. Everything seemed fine, except for one detail: if we have a camera component that provides tens if not hundreds of new values every second, and we take into consideration that we have more than just the camera in a game, we can see that the number of service method calls performed by the broadcaster to transmit state variable changes is in the order of hundreds (at least) per second. This will cripple the service, regardless of the hardware it runs on (provided we stick to the “cheap” area…). A way to seriously cut down the number of service method calls was needed.
One way to reduce the service calls is to buffer the state variable changes, i.e. store each value together with the time at which the change occurred, and after a specific amount of time, send all buffered variable changes to the service, which in turn redistributes them to the observers, which reconstruct the sequence of state variable changes using the information received and timers. We call each such buffer a TimeSlice, and a touple of the form <VarName, VarValue, TimeSpan> a SliceEntry, where the TimeSpan is the time interval passed since the beginning of the current TimeSlice.
At this point we decided to call the new component a CommunicationBroker. It became clear that all code that would involve the Streaming Service would now be placed in the CommunicationBroker, and that sending calls/responding to the Streaming Service can be abstracted through this broker. In fact we now obtained an XNA Streaming Framework. This significantly reduces the complexity of the code that is necessary in the streamed game. Further more, now we had an actual streaming part, we stream the variable changes.
This is the end of part one of the article. In subsequent parts, I will describe each component in more detail and present some preliminary test results.