diff --git a/tools/chatgui/tests/test_call_video_clock.cpp b/tools/chatgui/tests/test_call_video_clock.cpp index 1ab3a95a..d10d6a39 100644 --- a/tools/chatgui/tests/test_call_video_clock.cpp +++ b/tools/chatgui/tests/test_call_video_clock.cpp @@ -33,7 +33,10 @@ static size_t threadId() { return std::hash{}(std::this_thread: static int64_t nowUs() { return std::chrono::duration_cast(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 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 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);