Continuum v2 – Open Capture Framework
Continuum is an open framework designed to read and write changes in state. It supports forward and backwards playback and random seek and is designed to be streamed over a network. The data is captured in a format that can be reused, replayed, repurposed and investigated in much further detail than the flat view provided by a video capture.
While in VastPark we use Continuum for “deep recording” the scene, it can have other uses outside of virtual worlds also.
I can think of many industries (ie: finance, manufacture, emergency services) where being able to capture a series of events for analysis later is of great benefit.
In v1, Continuum was limited to captures of IMML states; any time an element was added, removed or updated, a corresponding Continuum entry would be generated and added into a filestream.
This made it possible to record what was going on inside of the virtual world both client and server side, as initially everything being used by world developers was IMML based.
Unfortunately, v1 came with a number of limitations due to it’s ties with IMML:
- Live audio/video were not able to be captured as they aren’t static resources and the IMML just pointed to the stream. Playback of the Continuum file later would end up seeing different video/audio than when it was recorded. Or even worse, the stream no longer exists as is often the case with live events.
- Custom texture manipulation could not be captured as it skips the IMML layer and writes directly to the texture
- Custom animation (LIXA) uses direct bone manipulation which also skips the IMML layer
These limitations and others became quite frustrating, as additional features being added to the worlds platform often didn’t make sense to integrate into IMML and as a result could not be recorded easily.
With v2, lessons have been learned and some major changes to the way Continuum works have been made.
- API for building custom state types
- Support for an almost infinite (~2 billion) number of arbitrary state types per stream
- Support for compressed and/or encrypted states
- Concurrent playback of multiple streams on a single timeline
- Concurrent record of states into the one stream
The design for v2 is a complete overhaul of v1 and revolves around the concept of state controllers and recorders. These constructs work against capture state instances, which is what a Continuum stream is composed of.
The header of a v2 Continuum stream looks like this:
Of note is the inclusion of the State Allocation Table (or SAT) which provides the glue between the custom state types and a stream. Each state controller has a GUID that the stream stores alongside an internal stream identifier:
The body of a Continuum stream contains sequential blocks of capture states. Each state node is self contained and stores an array of bytes:
Find the code under the Continuum and Continuum.Imml folders here.
If you’d like to have a go at building your own capture types, you really only need to play with two interfaces, IStateController and IStateRecorder which are fed into the StateRegistry and the CaptureService respectively.
They look like this:
During a record, the buffer of the IStateRecorder is polled and written into the capture stream. Objects should be monitored for change and inserted into the buffer of the IStateRecorder at that time.
During playback, the Create and Execute methods of IStateController are used to recreate the state and then execute it at the appropriate time.
I’ll blog at a later date showing how to do this in more detail, along with taking Continuum in the other direction and integrating it into your own application outside of VastPark.