Distinguish encoder KEY checks from receiver capability probes in tests

This commit is contained in:
evgeny committed 2026-10-20 01:27:03 +02:00
1 parent 4db89eeb32
commit 475bec52ca
1 file changed
+18 -6
+18 -6
View File
@@ -33,7 +33,10 @@ static size_t threadId() { return std::hash<std::thread::id>{}(std::this_thread:
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) {
if (av_codec_is_decoder(codec)) ++decoderOpens;
if (av_codec_is_decoder(codec)) {
// Отделяем RX-пробы от дополнительного software decoder внутри проверки encoder KEY.
if (context->thread_type == FF_THREAD_SLICE) ++decoderOpens;
}
else if (cancelEncoderProbe) *cancelEncoderProbe = false;
++codecOpens; return __real_avcodec_open2(context, codec, options);
}
@@ -121,7 +124,9 @@ int main(int argc, char** argv) {
// Отмена после готового decoder, но посреди encoder: частичная общая матрица не должна попасть в кэш.
std::atomic<bool> interrupted{true}; cancelEncoderProbe = &interrupted;
const auto abandoned = CallVideoEngine::capabilities(&interrupted); cancelEncoderProbe = nullptr;
if (interrupted || abandoned.encode[0].profiles || abandoned.decode[0].profiles || !decoderOpens) return 1;
if (interrupted || abandoned.encode[0].profiles || abandoned.decode[0].profiles || !decoderOpens) {
DEBUG_ERROR(DEBUG_CATEGORY_CALL, "cancelled codec preparation published partial capabilities or missed cancellation"); return 1;
}
const unsigned decodedBeforeWarmup = decoderOpens;
// Как при старте GUI: подготовка в worker, event loop работает, повторный вызов не открывает codec.
std::atomic<bool> preparing{true}, prepared{false};
@@ -132,16 +137,23 @@ int main(int argc, char** argv) {
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
|| decoderOpens != decodedBeforeWarmup) return 1;
if (!ticks || !ready.decode[0].profiles || !ready.decode[1].profiles || !codecOpens || decoderOpens != decodedBeforeWarmup) {
DEBUG_ERROR(DEBUG_CATEGORY_CALL, "background preparation failed ticks=%u decode=%u/%u opens=%u decoder_opens=%u->%u",
ticks, ready.decode[0].profiles, ready.decode[1].profiles, codecOpens.load(), decodedBeforeWarmup, decoderOpens.load()); return 1;
}
const unsigned opened = codecOpens;
const auto cancelled = CallVideoEngine::capabilities(&preparing);
if (cancelled.encode[0].profiles || cancelled.decode[0].profiles) return 1;
if (cancelled.encode[0].profiles || cancelled.decode[0].profiles) {
DEBUG_ERROR(DEBUG_CATEGORY_CALL, "cancelled codec preparation returned capabilities"); 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;
|| memcmp(expected, actual, sizeof(actual)) || codecOpens != opened) {
DEBUG_ERROR(DEBUG_CATEGORY_CALL, "warm codec access changed capabilities or repeated probe opens=%u->%u", opened, codecOpens.load());
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);