Frame Submission & Synchronization

1. Overview

The communication between IN plugins (game telemetry producers) and the OpenSR host is based on a frame submission mechanism.

This mechanism ensures:

  • consistent telemetry flow
  • controlled update rates
  • safe cross-thread synchronization

2. Submission Mechanism

The OpenSRContext provides:

void (*submitFrameCallback)(void* userData);
void* userData;

Usage:

m_pContext->submitFrameCallback(m_pContext->userData);

3. userData Contract

Rules:

  • context->userData is mandatory
  • It must be passed as-is
  • It must never be modified

Strict requirement:

// Correct
submitFrameCallback(context->userData);

// Forbidden
submitFrameCallback(customPointer);

Rationale:

This pointer is internally managed by the host and ensures:

  • correct routing
  • internal state tracking
  • thread safety

4. Frame Submission Rules

4.1 Fresh Data Only

Plugins must:

  • submit only new telemetry frames
  • avoid resubmitting unchanged data

Correct pattern:

if (updateNeeded) {
    m_pContext->submitFrameCallback(m_pContext->userData);
}

Important:

  • Submitting duplicate frames is considered incorrect behavior
  • The host may detect and ignore redundant data

4.2 Submission Frequency

  • Plugins must submit at the game telemetry rate
  • The plugin is responsible for:
    • matching the real update frequency of the game

If frames are skipped:

  • This indicates a plugin implementation issue
  • The host does not compensate for missing frames

4.3 High Frequency Behavior

Even if a plugin submits very fast (e.g., 4000 Hz):

  • The host applies its own internal rate limiting
  • User-configurable modes:
ModeFrequency
Default~30 Hz
Pro Performance Mode500+ Hz

Result:

  • Excess submissions are safely throttled
  • No risk of flooding the system

5. Thread Safety & Blocking Behavior

Thread Safety:

  • submitFrameCallback is thread-safe

Blocking:

  • The call is blocking during execution

Reentrancy:

  • Re-entering the callback from within itself is not possible
  • Nested calls are not allowed

6. Recommended Worker Loop Pattern

Typical IN plugin loop:

while (!m_stopRequested) {
    if (m_isPluginPaused) {
        std::unique_lock<std::mutex> lock(m_pauseMutex);
        m_pauseCv.wait(lock);
    }

    bool updateNeeded = ReadGameTelemetry();

    if (updateNeeded) {
        m_pContext->submitFrameCallback(m_pContext->userData);
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(n));
}

7. Host Processing (Conceptual)

When a frame is submitted:

  1. Host receives callback
  2. Validates telemetry data
  3. Adds internal metadata (e.g., frame ID)
  4. Dispatches to all active OUT plugins

8. Design Intent

This model ensures:

  • Decoupling
    • IN plugins control when data is ready
  • Stability
    • Host controls final processing rate
  • Performance scalability
    • Supports low-end and high-end setups
  • Determinism
    • One callback = one valid frame

9. Common Mistakes (Important for SDK)

Plugins must avoid:

  • Modifying userData
  • Submitting:
    • stale data
    • duplicated frames
  • Calling callback:
    • without new telemetry
  • Trying to match host frequency instead of game frequency

10. Usage Model

  • IN plugin = producer (event-driven)
  • Host = rate controller + dispatcher
  • OUT plugins = consumers (polling/loop-based)