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->userDatais 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:
| Mode | Frequency |
|---|---|
| Default | ~30 Hz |
| Pro Performance Mode | 500+ Hz |
Result:
- Excess submissions are safely throttled
- No risk of flooding the system
5. Thread Safety & Blocking Behavior
Thread Safety:
submitFrameCallbackis 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:
- Host receives callback
- Validates telemetry data
- Adds internal metadata (e.g., frame ID)
- 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)
