[client/idd] preserve frame timing across reconnects

This commit is contained in:
Geoffrey McRae
2026-08-04 13:34:34 +10:00
parent 5ebc208d43
commit 5be46121a2
2 changed files with 23 additions and 38 deletions

View File

@@ -47,7 +47,6 @@ static struct
_Atomic(uint32_t) generation; _Atomic(uint32_t) generation;
_Atomic(uint64_t) period; _Atomic(uint64_t) period;
uint64_t lastSend; uint64_t lastSend;
uint64_t lastCadence;
int64_t phaseError; int64_t phaseError;
uint32_t feedbackFrameSerial; uint32_t feedbackFrameSerial;
@@ -177,15 +176,10 @@ void frameScheduler_start(LG_TransportFeatureFlags features)
features & LG_TRANSPORT_FEATURE_FRAME_SCHEDULE; features & LG_TRANSPORT_FEATURE_FRAME_SCHEDULE;
l_frameScheduler.active = false; l_frameScheduler.active = false;
l_frameScheduler.controlPending = false; l_frameScheduler.controlPending = false;
l_frameScheduler.period = 0;
l_frameScheduler.lastSend = 0; l_frameScheduler.lastSend = 0;
l_frameScheduler.lastCadence = 0;
++l_frameScheduler.generation; ++l_frameScheduler.generation;
LG_LOCK(l_frameScheduler.lock); LG_LOCK(l_frameScheduler.lock);
l_frameScheduler.renderSampleIndex = 0;
l_frameScheduler.renderSampleCount = 0;
l_frameScheduler.lastRender = 0;
l_frameScheduler.phaseError = 0; l_frameScheduler.phaseError = 0;
l_frameScheduler.feedbackFrameSerial = 0; l_frameScheduler.feedbackFrameSerial = 0;
l_frameScheduler.feedbackSamples = 0; l_frameScheduler.feedbackSamples = 0;
@@ -209,29 +203,16 @@ void frameScheduler_update(void)
return; return;
const uint64_t now = nanotime(); const uint64_t now = nanotime();
const uint64_t period = presentationPeriod(); uint64_t period = presentationPeriod();
if (period < FRAME_SCHEDULER_MIN_PERIOD_NS || if (period < FRAME_SCHEDULER_MIN_PERIOD_NS ||
period > FRAME_SCHEDULER_MAX_PERIOD_NS) period > FRAME_SCHEDULER_MAX_PERIOD_NS)
{ {
if (l_frameScheduler.active && l_frameScheduler.lastCadence && period = l_frameScheduler.period;
now - l_frameScheduler.lastCadence > FRAME_SCHEDULER_RENEW_NS * 2) if (period < FRAME_SCHEDULER_MIN_PERIOD_NS ||
{ period > FRAME_SCHEDULER_MAX_PERIOD_NS)
if (sendSchedule(LG_TRANSPORT_FRAME_SCHEDULE_RELEASE, 0))
{
l_frameScheduler.active = false;
l_frameScheduler.period = 0;
LG_LOCK(l_frameScheduler.lock);
l_frameScheduler.phaseError = 0;
l_frameScheduler.feedbackFrameSerial = 0;
l_frameScheduler.feedbackSamples = 0;
l_frameScheduler.feedbackDirty = false;
LG_UNLOCK(l_frameScheduler.lock);
}
}
return; return;
} }
l_frameScheduler.lastCadence = now;
bool reset = !l_frameScheduler.period; bool reset = !l_frameScheduler.period;
if (!reset) if (!reset)
{ {

View File

@@ -104,8 +104,8 @@ void CFrameScheduler::ElectOwner(uint64_t now)
m_scheduling = true; m_scheduling = true;
} }
if (oldClientID != m_schedule.clientID || const bool ownerChanged = oldClientID != m_schedule.clientID;
oldGeneration != m_schedule.generation) if (ownerChanged || oldGeneration != m_schedule.generation)
{ {
m_nextDeadline = m_scheduling ? now + m_schedule.period : 0; m_nextDeadline = m_scheduling ? now + m_schedule.period : 0;
m_forceNext = m_scheduling; m_forceNext = m_scheduling;
@@ -117,11 +117,11 @@ void CFrameScheduler::ElectOwner(uint64_t now)
m_lastLogSkipped = m_skippedFrames; m_lastLogSkipped = m_skippedFrames;
m_lastLogPublished = m_publishedFrames; m_lastLogPublished = m_publishedFrames;
if (m_scheduling) if (ownerChanged && m_scheduling)
DEBUG_INFO("Frame timing owner %u generation %u at %.3f Hz", DEBUG_INFO("Frame timing owner %u generation %u at %.3f Hz",
m_schedule.clientID, m_schedule.generation, m_schedule.clientID, m_schedule.generation,
1000000000.0 / m_schedule.period); 1000000000.0 / m_schedule.period);
else if (oldClientID) else if (ownerChanged && oldClientID)
DEBUG_INFO("Frame timing owner released; using push delivery"); DEBUG_INFO("Frame timing owner released; using push delivery");
} }
} }
@@ -202,21 +202,25 @@ bool CFrameScheduler::UpdateSchedule(const KVMFRFrameSchedule& schedule,
AcquireSRWLockExclusive(&m_lock); AcquireSRWLockExclusive(&m_lock);
Client * client = FindClient(schedule.clientID); Client * client = FindClient(schedule.clientID);
if (!client || !client->subscribed)
{
ReleaseSRWLockExclusive(&m_lock);
return false;
}
if (schedule.flags & KVMFR_FRAME_SCHEDULE_RELEASE) if (schedule.flags & KVMFR_FRAME_SCHEDULE_RELEASE)
{
if (client && client->subscribed)
{ {
client->active = false; client->active = false;
client->expiry = 0; client->expiry = 0;
ElectOwner(now); ElectOwner(now);
}
ReleaseSRWLockExclusive(&m_lock); ReleaseSRWLockExclusive(&m_lock);
return true; return true;
} }
if (!client || !client->subscribed)
{
ReleaseSRWLockExclusive(&m_lock);
return false;
}
if (!(schedule.flags & KVMFR_FRAME_SCHEDULE_ACTIVE) || if (!(schedule.flags & KVMFR_FRAME_SCHEDULE_ACTIVE) ||
schedule.period < MIN_PERIOD_NS || schedule.period < MIN_PERIOD_NS ||
schedule.period > MAX_PERIOD_NS || schedule.period > MAX_PERIOD_NS ||