Exercise codec output delay explicitly in the desktop fixture

This commit is contained in:
evgeny committed 2026-10-14 14:04:45 +02:00
1 parent 5ce2877fc0
commit 8d0504c759
2 files changed
+33 -4

No files matched your search

+31 -3
View File
@@ -10,6 +10,7 @@
#include <atomic>
#include <cmath>
#include <chrono>
#include <deque>
extern "C" {
#include "utun_instance.h"
@@ -29,12 +30,39 @@ extern "C" {
static QList<QByteArray> snapshots;
#if defined(TEST_NULL_AUDIO) && defined(HAVE_FFMPEG)
static std::atomic<bool> delayedDecoder{false};
static AVCodecContext* delayedContext = nullptr;
static std::deque<AVFrame*> delayedFrames;
static bool delayedDraining = false;
extern "C" int __real_avcodec_open2(AVCodecContext*, const AVCodec*, AVDictionary**);
extern "C" int __wrap_avcodec_open2(AVCodecContext* context, const AVCodec* codec, AVDictionary** options) {
if (delayedDecoder && av_codec_is_decoder(codec)) {
context->thread_count = 4; context->thread_type = FF_THREAD_FRAME;
int result = __real_avcodec_open2(context, codec, options);
if (!result && delayedDecoder && codec && av_codec_is_decoder(codec)) {
delayedContext = context; delayedDraining = false;
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "fixture decoder name=%s holds four real decoded frames before output", codec->name);
}
return __real_avcodec_open2(context, codec, options);
return result;
}
extern "C" int __real_avcodec_receive_frame(AVCodecContext*, AVFrame*);
extern "C" int __wrap_avcodec_receive_frame(AVCodecContext* context, AVFrame* frame) {
if (context != delayedContext) return __real_avcodec_receive_frame(context, frame);
int result = __real_avcodec_receive_frame(context, frame);
if (!result) {
AVFrame* held = av_frame_clone(frame); if (!held) return AVERROR(ENOMEM);
delayedFrames.push_back(held); av_frame_unref(frame);
} else if (result == AVERROR_EOF) delayedDraining = true;
else if (result != AVERROR(EAGAIN)) return result;
if ((delayedDraining || delayedFrames.size() >= 4) && !delayedFrames.empty()) {
AVFrame* held = delayedFrames.front(); delayedFrames.pop_front(); av_frame_move_ref(frame, held); av_frame_free(&held); return 0;
}
return delayedDraining ? AVERROR_EOF : AVERROR(EAGAIN);
}
extern "C" void __real_avcodec_free_context(AVCodecContext**);
extern "C" void __wrap_avcodec_free_context(AVCodecContext** context) {
if (context && *context == delayedContext) {
for (auto* frame : delayedFrames) av_frame_free(&frame);
delayedFrames.clear(); delayedContext = nullptr; delayedDraining = false;
}
__real_avcodec_free_context(context);
}
#endif
#ifdef TEST_NULL_AUDIO