Drain old GPU frames before bitrate replacement and poll outputs while blocked

This commit is contained in:
evgeny committed 2026-10-19 17:29:10 +02:00
1 parent 5f772fa97f
commit 13f09cfc20
3 files changed
+54 -72

No files matched your search

+7 -6
View File
@@ -262,7 +262,7 @@ void CallVideoEngine::transmit() {
}
}
if (format.generation && state.have_peer && !call_video_format_supported(&caps, &state.peer, &format)) appliedRevision = 0;
if (!enabled || !state.have_peer || pts <= lastPts) { idle(); continue; }
if (!enabled || !state.have_peer || pts < 0) { idle(); continue; }
if (revision != appliedRevision) {
call_video_format next{format.generation + 1, (uint16_t)width, (uint16_t)height, 30, 0, (uint8_t)codec, 0, 4000000, 0};
bool opened = false;
@@ -291,15 +291,16 @@ void CallVideoEngine::transmit() {
call_video_port_applied(m->id, format.generation, request, 0);
}
#ifdef HAVE_STREAM_CAPTURE
if (!state.can_encode) { idle(); continue; }
if (image.isNull() || nowUs() - pts > CallCameraMaxFrameAgeUs) {
bool submit = state.can_encode && pts > lastPts;
if (submit && (image.isNull() || nowUs() - pts > CallCameraMaxFrameAgeUs)) {
DEBUG_WARN(DEBUG_CATEGORY_CALL, "video TX skips old capture age_us=%lld", (long long)(nowUs() - pts));
lastPts = pts; ++expired; continue;
}
QList<LiveEncodedFrame> outputs; CallVideoRateCompletion completion;
int64_t encodeStarted = nowUs();
inputAgeMax = std::max(inputAgeMax, encodeStarted - pts);
bool encoded = encoder.encode(image, pts, forceKey, outputs, completion); lastPts = pts;
bool encoded = encoder.encode(submit ? image : QImage{}, pts, forceKey, outputs, completion);
if (submit) { lastPts = pts; if (encoded) forceKey = false; }
encodeMax = std::max(encodeMax, nowUs() - encodeStarted);
if (completion.request) {
call_video_port_applied(m->id, completion.generation, completion.request, completion.bitrate);
@@ -308,7 +309,7 @@ void CallVideoEngine::transmit() {
}
if (!encoded) { forceKey = true; m->report(encoder.error()); continue; }
// GPU может вернуть несколько уже готовых кадров: отправляем все, не добавляя очередь в TX worker.
if (outputs.isEmpty()) continue;
if (outputs.isEmpty()) { idle(); continue; }
if (outputs.size() > CALL_VIDEO_PORT_TX_FRAMES) {
DEBUG_ERROR(DEBUG_CATEGORY_CALL, "GPU output batch exceeds mailbox frames=%lld", (long long)outputs.size());
forceKey = true; continue;
@@ -329,7 +330,7 @@ void CallVideoEngine::transmit() {
(long long)(nowUs() - packets[0].pts_us), count);
expired += count; forceKey = true; pendingOutputs.clear(); continue;
}
pendingCount = count; forceKey = false; }
pendingCount = count; }
for (unsigned i = 0; i < count; ++i) {
const auto& output = pendingOutputs[i];
// Одинаковое окно исходного PTS на всех этапах: примерно один кадр в секунду, без трассы каждого кадра.