OptiTrack Timecode

Main PageBack to the NatNet SDK page

This page covers the timecode representation in Motive and how it can be accessed through the NatNet SDK library tools.

Timecode Integration[edit]

SMPTE Timecode signals can be integrated into OptiTrack motion capture systems through the eSync synchronization hub. To do this, simply connect a timecode sync source to the SMPTE Timecode Input of the eSync. Once the signal is detected, the corresponding timecode will be displayed at the top-right corner of the Perspective View pane in Motive. When you capture a Take with timecode signal, the information saved into the corresponding Take file.

Note: SMPTE Timecode integration requires the eSync hub.
  • Timecode display in Motive
  • The eSync 2 synchronization hub. SMPTE Timecode signal connects to the input port E.

  • Timecode Representation[edit]

    When SMPTE timecode signal is available within a system, each frame of data will contain an OptiTrack timecode stamp, which is an extended form of the typical studio SMPTE timecode stamp. Since the frame rate of an OptiTrack mocap system typically exceeds standard SMPTE timecode frame rates, an additional “subframe” value is added at the end of the timecode stamp. This “subframe” value is 0-based and indicates increments of captured mocap frames in between every SMPTE timecode frames:

    OptiTrack Timecode Representation: 120 fps mocap data, 30-fps no-drop SMPTE timecode source

    In the above sample representation, a 120 FPS motion capture session is synchronized to a sync source with 30 FPS no-drop SMPTE timecode signal. In this case, there is a 4 : 1 ratio of number motion capture frames to a single frame of the sync source, and the extra motion capture frames are represented by the OptiTrack SubFrame field in the OptiTrack timecode.

    The generic form for OptiTrack timecode: HH:MM:SS:FF.Y (hours:minutes:seconds:frames.subframe)

    NatNet: Timecode[edit]

    When using the NatNet SDK, the OptiTrack timecode is sent to NatNet clients in the form of two unsigned integers contained within the packet of sFrameOfMocapData:

    • OptiTrack encoded SMPTE timecode: Unsigned int Timecode
    • OptiTrack encoded sub-frame data: Unsigned int TimecodeSubframe

    When streaming, the Unsigned int Timecode parameter is interpreted differently when streaming from a live data (Live Mode) and when streaming from a recorded playback (Edit Mode).

    • Live mode: When streaming in real-time, the Timecode parameter is available only when SMPTE timecode signal is present in your mocap hardware setup; typically when using the eSync and a timecode generator. When present, the Timecode parameter will be a correctly formatted SMPTE timecode value.
    • Edit Mode: When streaming from a recorded playback, the Timecode parameter is the current frame number converted to SMPTE Timecode format.

    NatNet: Timecode Helper Functions[edit]

    Timecode values should not be used directly, but decoded using the provided NatNet tools. Within the NatNetClient class, there are methods for decoding the Timecode parameter and the TimecodeSubframe parameter (DecodeTimecode) and converting them into a string-friendly format (TimecodeStringify).


    Helper function to decode OptiTrack timecode data into individual timecode values

    bool	DecodeTimecode(unsigned int inTimecode, unsigned int inTimecodeSubframe, 
    							int* hour, int* minute, int* second, 
    							int* frame, int* subframe);


    Helper function to decode OptiTrack timecode into a user friendly string in the form “hh:mm:ss:ff:yy”

    bool	NatNet_TimecodeStringify(unsigned int inTimecode, unsigned int inTimecodeSubframe, 
    							char *Buffer, int BufferSize);

    C++ Sample

    The following is an example of how to decode timecode using the NatNet helper functions (from the SampleClient.cpp example):

    // decode timecode to values
    int	hour, minute, second, frame, subframe;
    bool	bValid = pClient->DecodeTimecode(data->Timecode, data->TimecodeSubframe, 
    					&hour, &minute, &second, &frame, &subframe);
    // decode timecode to friendly string
    char	szTimecode[128] = "";
    pClient->TimecodeStringify(data->Timecode, data->TimecodeSubframe, szTimecode, 128);
    printf("Timecode : %s\n", szTimecode);