Exercise delayed receive workers UI stalls and call restart with real video decoding
This commit is contained in:
1 parent
b211da9a04
commit
0d65c5bb74
2 files changed
+34
-11
No files matched your search
@@ -9,6 +9,7 @@
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
extern "C" {
|
||||
#include "../../../lib/mem.h"
|
||||
#include "../../../lib/debug_config.h"
|
||||
@@ -18,6 +19,7 @@ static call_video_format format{1, 640, 360, 30, 0, 1, 31, 4000000, 2};
|
||||
static std::atomic<int> requests{0}, rejects{0};
|
||||
static int cursor = 0;
|
||||
static int64_t start;
|
||||
static bool disturbed = false;
|
||||
static int64_t nowUs() { return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch()).count(); }
|
||||
extern "C" int __wrap_call_audio_get_clock(uint64_t, int64_t now, call_clock_snapshot* out) {
|
||||
*out = {}; out->valid = out->measured = 1; out->pts_us = 1000000 + now - start;
|
||||
@@ -29,10 +31,13 @@ extern "C" int __wrap_call_video_port_status(uint64_t, struct call_video_port_st
|
||||
extern "C" void __wrap_call_video_port_request_key(uint64_t) { ++requests; }
|
||||
extern "C" int __wrap_call_video_port_decoded(uint64_t, uint64_t, int accepted) { if (!accepted) ++rejects; return 0; }
|
||||
extern "C" int __wrap_call_video_port_pull(uint64_t id, call_video_frame* out) {
|
||||
if (cursor >= (int)frames.size() || nowUs() - start < cursor * 33333ll) return 0;
|
||||
const int64_t received = start + cursor * 33333ll + (disturbed && cursor == 30 ? 20000 : 0);
|
||||
if (cursor >= (int)frames.size() || nowUs() < received) return 0;
|
||||
// Кадр уже пришёл: остановка RX worker не должна подменить время доступности данных.
|
||||
if (disturbed && cursor == 60) QThread::msleep(80);
|
||||
const auto& f = frames[cursor]; *out = {}; out->call_id = id; out->format = format;
|
||||
out->pts_us = f.pts; out->frame_id = ++cursor; out->flags = f.key ? CALL_VIDEO_KEY : 0;
|
||||
out->received_us = start + (cursor - 1) * 33333ll;
|
||||
out->received_us = received;
|
||||
out->size = out->length = f.data.size(); auto* data = static_cast<uint8_t*>(u_malloc(out->size));
|
||||
memcpy(data, f.data.constData(), out->size); out->data = data; return 1;
|
||||
}
|
||||
@@ -46,11 +51,27 @@ int main(int argc, char** argv) {
|
||||
if (!encoder.encode(image, 1000000 + i * 33333ll, i == 0, frame, completion)) return 3;
|
||||
frames.push_back(frame);
|
||||
}
|
||||
int shown = 0; CallVideoEngine engine;
|
||||
QObject::connect(&engine, &CallVideoEngine::imageChanged, [&](const QImage& frame) { if (!frame.isNull()) ++shown; });
|
||||
start = nowUs(); engine.start(7); QElapsedTimer timer; timer.start();
|
||||
while (timer.elapsed() < 3200) { app.processEvents(); QThread::msleep(2); }
|
||||
engine.stop();
|
||||
fprintf(stderr, "CLOCK PROBE shown=%d/90 key_requests=%d decoder_rejections=%d audio_epochs=32\n", shown, requests.load(), rejects.load());
|
||||
return shown >= 85 && requests == 0 && rejects == 0 ? 0 : 1;
|
||||
CallVideoEngine engine; std::vector<int64_t> published;
|
||||
QObject::connect(&engine, &CallVideoEngine::imageChanged, [&](const QImage& frame) {
|
||||
if (!frame.isNull()) published.push_back(nowUs());
|
||||
});
|
||||
for (int scenario = 0; scenario < 2; ++scenario) {
|
||||
disturbed = scenario != 0; cursor = 0; published.clear();
|
||||
start = nowUs(); engine.start(7); QElapsedTimer timer; timer.start(); bool uiPaused = false;
|
||||
while (timer.elapsed() < 3200) {
|
||||
if (disturbed && !uiPaused && timer.elapsed() >= 1500) { QThread::msleep(60); uiPaused = true; }
|
||||
app.processEvents(); QThread::msleep(2);
|
||||
}
|
||||
engine.stop(); const auto stoppedCount = published.size(); app.processEvents();
|
||||
if (published.size() != stoppedCount) { DEBUG_ERROR(DEBUG_CATEGORY_CALL, "stale video publication after stop"); return 1; }
|
||||
std::vector<int64_t> gaps;
|
||||
for (size_t i = 1; i < published.size(); ++i) gaps.push_back(published[i] - published[i - 1]);
|
||||
std::sort(gaps.begin(), gaps.end());
|
||||
DEBUG_INFO(DEBUG_CATEGORY_CALL, "CLOCK PROBE disturbed=%d shown=%zu/90 key_requests=%d decoder_rejections=%d "
|
||||
"gap_p50_us=%lld gap_p95_us=%lld gap_max_us=%lld audio_epochs=32", disturbed, published.size(), requests.load(), rejects.load(),
|
||||
(long long)(gaps.empty() ? 0 : gaps[gaps.size() / 2]), (long long)(gaps.empty() ? 0 : gaps[gaps.size() * 95 / 100]),
|
||||
(long long)(gaps.empty() ? 0 : gaps.back()));
|
||||
if (published.size() < (disturbed ? 82u : 85u) || requests || rejects) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user