Browse Source

Retain jitter tolerance across desktop camera phase drift

master
evgeny 5 days ago
parent
commit
f8e960c844
  1. 19
      tools/chatgui/src/call_video_cadence.h
  2. 13
      tools/chatgui/tests/test_call_video_encoder.cpp

19
tools/chatgui/src/call_video_cadence.h

@ -1,17 +1,20 @@
#pragma once
#include <cstdint>
// Сетка 30 fps с допуском четверти периода: дрожание PTS не превращает 30 fps в 15.
// Бюджет 30 fps с запасом четверти кадра на дрожание PTS, без накопления после паузы.
class CallVideoCadence {
int64_t origin = -1, lastSlot = -1;
int64_t lastPts = -1, credit = 1250000;
public:
bool accept(int64_t pts) {
if (origin < 0) origin = pts;
if (pts < origin) return false;
const int64_t elapsed = pts - origin;
const int64_t slot = (elapsed / 1000000) * 30 + ((elapsed % 1000000) * 30 + 250000) / 1000000;
if (slot <= lastSlot) return false;
lastSlot = slot;
if (lastPts >= 0) {
if (pts <= lastPts) return false;
const int64_t elapsed = pts - lastPts;
credit = elapsed >= 41667 ? 1250000 : credit + elapsed * 30;
if (credit > 1250000) credit = 1250000;
}
lastPts = pts;
if (credit < 1000000) return false;
credit -= 1000000;
return true;
}
};

13
tools/chatgui/tests/test_call_video_encoder.cpp

@ -51,6 +51,19 @@ private slots:
QVERIFY(jittered.accept(30000000)); // Долгая пауза не создаёт догоняющий burst.
QVERIFY(!jittered.accept(30001000));
}
void captureCadenceDrift() {
CallVideoCadence camera;
// Квантование камерой до миллисекунд и медленный уход фазы относительно сетки 30 fps.
for (int i = 0; i < 18000; i++) {
const int64_t pts = 1000000 + (i * 33340LL / 1000) * 1000 + (i % 2 ? -1500 : 1500);
QVERIFY2(camera.accept(pts), qPrintable(QString("Dropped camera frame %1 at %2").arg(i).arg(pts)));
QVERIFY(!camera.accept(pts));
}
CallVideoCadence fast;
int accepted = 0;
for (int i = 0; i < 24000; i++) if (fast.accept(1000000 + i * 25000LL)) accepted++;
QCOMPARE(accepted, 18000); // Допуск не превращает ограничение 30 fps в 40 fps.
}
void initTestCase() {
debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN); debug_set_category_level(DEBUG_CATEGORY_CALL, DEBUG_LEVEL_DEBUG);
av_log_set_level(AV_LOG_ERROR);

Loading…
Cancel
Save