Finish decoder capability probes after first paced output and drain
This commit is contained in:
1 parent
7ae204ba4f
commit
8ad5c09474
2 files changed
+42
-9
No files matched your search
@@ -25,9 +25,10 @@ static QByteArray selected;
|
||||
static unsigned opened = 0, software = 0;
|
||||
static int depth = 1;
|
||||
static bool burst = false, badReplacement = false, badProbe = false;
|
||||
struct DecodePending { std::deque<AVFrame*> frames; bool eos = false; };
|
||||
struct DecodePending { std::deque<AVFrame*> frames; bool eos = false; unsigned inputs = 0; };
|
||||
static std::map<AVCodecContext*, DecodePending> decoderContexts;
|
||||
static bool delayedDecoder = false;
|
||||
static unsigned probeInputs = 0, probeOutputs = 0, probeMaxInputs = 0;
|
||||
|
||||
extern "C" const AVCodec* __real_avcodec_find_encoder_by_name(const char*);
|
||||
extern "C" const AVCodec* __wrap_avcodec_find_encoder_by_name(const char* name) {
|
||||
@@ -116,6 +117,9 @@ extern "C" void __wrap_avcodec_free_context(AVCodecContext** context) {
|
||||
extern "C" int __real_avcodec_send_packet(AVCodecContext*, const AVPacket*);
|
||||
extern "C" int __wrap_avcodec_send_packet(AVCodecContext* context, const AVPacket* packet) {
|
||||
int result = __real_avcodec_send_packet(context, packet);
|
||||
if (delayedDecoder && packet && result >= 0) {
|
||||
++probeInputs; probeMaxInputs = std::max(probeMaxInputs, ++decoderContexts[context].inputs);
|
||||
}
|
||||
if (delayedDecoder && !packet && result >= 0) decoderContexts[context].eos = true;
|
||||
return result;
|
||||
}
|
||||
@@ -129,6 +133,7 @@ extern "C" int __wrap_avcodec_receive_frame(AVCodecContext* context, AVFrame* ou
|
||||
if (result < 0 && result != AVERROR(EAGAIN) && result != AVERROR_EOF) return result;
|
||||
if (state.frames.empty()) return result;
|
||||
if (!state.eos && state.frames.size() <= 2) return AVERROR(EAGAIN);
|
||||
++probeOutputs;
|
||||
av_frame_move_ref(output, state.frames.front()); av_frame_free(&state.frames.front()); state.frames.pop_front(); return 0;
|
||||
}
|
||||
|
||||
@@ -138,9 +143,26 @@ private slots:
|
||||
void initTestCase() { debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN); av_log_set_level(AV_LOG_ERROR); }
|
||||
void init() {
|
||||
selected.clear(); opened = software = 0; depth = 1; burst = badReplacement = badProbe = delayedDecoder = false;
|
||||
probeInputs = probeOutputs = probeMaxInputs = 0;
|
||||
QVERIFY(contexts.empty()); QVERIFY(decoderContexts.empty());
|
||||
}
|
||||
void cleanup() { QVERIFY(contexts.empty()); QVERIFY(decoderContexts.empty()); }
|
||||
void capabilityProbeDrainsFirstOutput() {
|
||||
// Реальный software decoder выдаёт первый кадр только после третьего input, затем хранит хвост до EOS.
|
||||
delayedDecoder = true;
|
||||
QElapsedTimer timer; timer.start();
|
||||
const auto caps = CallVideoDecoder::capabilities();
|
||||
for (const auto& limit : caps.decode) {
|
||||
QCOMPARE(limit.profiles, uint8_t(3)); QCOMPARE(limit.fps, uint16_t(60));
|
||||
QCOMPARE(limit.width, uint16_t(1920)); QCOMPARE(limit.height, uint16_t(1920));
|
||||
}
|
||||
QVERIFY(probeInputs > 0); QCOMPARE(probeMaxInputs, 3u); QCOMPARE(probeOutputs, probeInputs);
|
||||
const unsigned before = probeInputs;
|
||||
const auto cached = CallVideoDecoder::capabilities();
|
||||
QCOMPARE(cached.decode[0].profiles, caps.decode[0].profiles); QCOMPARE(probeInputs, before);
|
||||
qInfo("Decoder capability probe with delayed output: %lldms, inputs=%u outputs=%u max_per_mode=%u",
|
||||
timer.elapsed(), probeInputs, probeOutputs, probeMaxInputs);
|
||||
}
|
||||
void delayedDecodeAndGenerationDrain() {
|
||||
LiveVideoEncoder encoder; LiveVideoConfig config;
|
||||
config.width = 640; config.height = 360; config.codec = 1; config.backend = "libx264";
|
||||
|
||||
Reference in new issue
Block a user