Log retained video batches and verify every GPU input across bitrate changes

This commit is contained in:
evgeny committed 2026-10-19 17:31:15 +02:00
1 parent 486d3314ef
commit 0e53a9f5dd
2 files changed
+23 -3

No files matched your search

+13
View File
@@ -27,6 +27,8 @@ static struct {
struct call_video_frame tx[CALL_VIDEO_PORT_TX_FRAMES], rx[8];
unsigned tx_count;
int tx_processing;
int64_t tx_wait_started;
unsigned tx_retries;
unsigned count, bytes;
uint64_t decoded_generation;
int decoded_pending, decoded_accepted;
@@ -43,6 +45,7 @@ static int schedule(void) {
static void clear_frames(void) {
for (unsigned i = 0; i < port.tx_count; ++i) u_free((void *)port.tx[i].data);
port.tx_count = 0;
port.tx_wait_started = 0; port.tx_retries = 0;
for (unsigned i = 0; i < port.count; ++i) u_free((void *)port.rx[i].data);
port.count = port.bytes = 0;
}
@@ -170,6 +173,16 @@ static void process(void *arg) {
if (!sent && active) {
port.tx_count = tx_count - sent_count;
memcpy(port.tx, tx + sent_count, port.tx_count * sizeof(*tx));
if (!port.tx_wait_started) {
port.tx_wait_started = call_video_playout_now_us();
DEBUG_WARN(DEBUG_CATEGORY_CALL, "video port TX paused call=%llu retained=%u first=%llu; chain preserved",
(unsigned long long)id, port.tx_count, (unsigned long long)port.tx[0].frame_id);
}
port.tx_retries++;
} else if (port.tx_wait_started) {
DEBUG_INFO(DEBUG_CATEGORY_CALL, "video port TX resumed call=%llu wait_us=%lld retries=%u result=%d",
(unsigned long long)id, (long long)(call_video_playout_now_us() - port.tx_wait_started), port.tx_retries, sent);
port.tx_wait_started = 0; port.tx_retries = 0;
}
if (sent < 0) ++port.status.key_serial;
}
+10 -3
View File
@@ -17,6 +17,7 @@ extern "C" {
struct Pending {
std::deque<AVPacket*> packets;
unsigned inputs = 0, serial = 0;
bool draining = false;
};
static std::mutex lock;
static std::map<AVCodecContext*, Pending> contexts;
@@ -74,7 +75,10 @@ extern "C" int __wrap_avcodec_open2(AVCodecContext* context, const AVCodec* code
extern "C" int __real_avcodec_send_frame(AVCodecContext*, const AVFrame*);
extern "C" int __wrap_avcodec_send_frame(AVCodecContext* context, const AVFrame* frame) {
int result = __real_avcodec_send_frame(context, frame);
if (result >= 0 && frame) { std::lock_guard<std::mutex> guard(lock); ++contexts[context].inputs; }
if (result >= 0) {
std::lock_guard<std::mutex> guard(lock);
if (frame) ++contexts[context].inputs; else contexts[context].draining = true;
}
return result;
}
extern "C" int __real_avcodec_receive_packet(AVCodecContext*, AVPacket*);
@@ -87,8 +91,9 @@ extern "C" int __wrap_avcodec_receive_packet(AVCodecContext* context, AVPacket*
if (badReplacement && state.serial >= 4) packet->flags &= ~AV_PKT_FLAG_KEY;
state.packets.push_back(packet);
} else av_packet_free(&packet);
if (result < 0 && result != AVERROR(EAGAIN)) return result;
bool ready = burst ? state.inputs % 3 == 0 : state.packets.size() > size_t(depth);
if (result < 0 && result != AVERROR(EAGAIN) && result != AVERROR_EOF) return result;
if (result == AVERROR_EOF && state.packets.empty()) return result;
bool ready = state.draining || (burst ? state.inputs % 3 == 0 : state.packets.size() > size_t(depth));
if (!ready || state.packets.empty()) return AVERROR(EAGAIN);
av_packet_move_ref(output, state.packets.front()); av_packet_free(&state.packets.front()); state.packets.pop_front(); return 0;
}
@@ -145,6 +150,7 @@ private slots:
}
maximumBatch = std::max(maximumBatch, unsigned(output.size()));
for (const auto& frame : output) {
QCOMPARE(frame.pts, 1234567 + shown * 33333ull); // Ни одного потерянного PTS при замене encoder.
QVERIFY(frame.pts > last); QVERIFY(frame.pts <= pts);
QCOMPARE((frame.pts - 1234567) % 33333, uint64_t(0));
QVERIFY(pts - frame.pts <= (batch ? 2u : 1u) * 33333);
@@ -156,6 +162,7 @@ private slots:
}
}
QVERIFY(shown >= 115); QCOMPARE(completed, !reject); QCOMPARE(failed, reject);
QCOMPARE(shown + encoder.pendingFrames(), 120u);
QCOMPARE(encoder.bitrate(), reject ? 1000000u : 300000u);
if (batch) QVERIFY(maximumBatch >= 2);
qInfo("GPU pipeline %s shown=%u max_batch=%u rollback=%d", selected.constData(), shown, maximumBatch, failed);