Exercise codec output delay explicitly in the desktop fixture
This commit is contained in:
1 parent
5ce2877fc0
commit
8d0504c759
2 files changed
+33
-4
No files matched your search
@@ -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
|
||||
|
||||
Reference in new issue
Block a user