Verify startup codec preparation keeps GUI responsive and reuses probes

This commit is contained in:
evgeny committed 2026-10-20 01:23:21 +02:00
1 parent 91478e2593
commit 36e8ab228c
2 files changed
+27 -1

No files matched your search

@@ -25,10 +25,15 @@ static int64_t start;
static bool disturbed = false;
static bool slowDecoder = false, holdAck = false, limitedDisplay = false;
static std::atomic<unsigned> decodedFrames{0};
static std::atomic<unsigned> codecOpens{0};
static std::atomic<size_t> displayThread{0};
static std::atomic<bool> unsafeTimer{false};
static size_t threadId() { return std::hash<std::thread::id>{}(std::this_thread::get_id()); }
static int64_t nowUs() { return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch()).count(); }
extern "C" int __real_avcodec_open2(AVCodecContext*, const AVCodec*, AVDictionary**);
extern "C" int __wrap_avcodec_open2(AVCodecContext* context, const AVCodec* codec, AVDictionary** options) {
++codecOpens; return __real_avcodec_open2(context, codec, options);
}
extern "C" int __real_avcodec_receive_frame(AVCodecContext*, AVFrame*);
extern "C" int __wrap_avcodec_receive_frame(AVCodecContext* codec, AVFrame* frame) {
if (threadId() == displayThread.load()) unsafeTimer = true;
@@ -110,6 +115,27 @@ static bool queuePressure() {
int main(int argc, char** argv) {
QCoreApplication app(argc, argv); debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN);
debug_set_category_level(DEBUG_CATEGORY_CALL, DEBUG_LEVEL_DEBUG);
// Как при старте GUI: подготовка в worker, event loop работает, повторный вызов не открывает codec.
std::atomic<bool> preparing{true}, prepared{false};
call_video_caps ready{};
std::thread warmup([&] { ready = CallVideoEngine::capabilities(&preparing); prepared = true; });
QTimer pulse; pulse.setInterval(10); unsigned ticks = 0;
QObject::connect(&pulse, &QTimer::timeout, [&] { ++ticks; }); pulse.start();
const int64_t warming = nowUs();
while (!prepared && nowUs() - warming < 10000000) { app.processEvents(); QThread::msleep(1); }
preparing = false; warmup.join(); pulse.stop();
if (!ticks || !ready.decode[0].profiles || !ready.decode[1].profiles || !codecOpens) return 1;
const unsigned opened = codecOpens;
const auto cancelled = CallVideoEngine::capabilities(&preparing);
if (cancelled.encode[0].profiles || cancelled.decode[0].profiles) return 1;
for (int i = 0; i < 3; ++i) {
const auto cached = CallVideoEngine::capabilities();
uint8_t expected[CALL_VIDEO_CAPS_BYTES], actual[CALL_VIDEO_CAPS_BYTES];
if (call_video_caps_encode(&ready, expected) || call_video_caps_encode(&cached, actual)
|| memcmp(expected, actual, sizeof(actual)) || codecOpens != opened) return 1;
}
DEBUG_INFO(DEBUG_CATEGORY_CALL, "PASS video background preparation elapsed_us=%lld gui_ticks=%u codec_opens=%u; "
"cancelled access preserves cache, three warm accesses open no codecs", (long long)(nowUs() - warming), ticks, opened);
if (!queuePressure()) return 1;
CallVideoEncoder encoder; if (!encoder.open(format, 1000000, "libx264")) return 2;
QImage image(640, 360, QImage::Format_RGB32); image.fill(Qt::blue);