Exercise audio continuity during video stalls and generation changes

This commit is contained in:
evgeny committed 2026-10-21 01:03:19 +02:00
1 parent 1764603977
commit c6ed01110e
2 files changed
+27 -5

No files matched your search

+12 -5
View File
@@ -255,7 +255,7 @@ void StreamPlayerWindow::decode() {
uint64_t audioPackets = 0, videoPackets = 0, batches = 0, batchMax = 0;
int64_t feedMax = 0, pullMax = 0, workMax = 0;
auto fail = [&](const QString& reason, bool retry = true) {
p.failed = true; p.complete = true;
p.failed = retry; p.complete = true; p.running = false;
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop audio worker failed id=%llu retry=%d: %s",
(unsigned long long)p.id, retry, qPrintable(reason));
emit statusChanged(reason); p.notify();
@@ -455,10 +455,10 @@ void StreamPlayerWindow::decodeVideo() {
while (p.running && !p.failed) {
uint64_t version;
{ std::lock_guard<std::mutex> guard(p.wakeLock); version = p.wakeVersion; }
uint64_t current; bool space;
uint64_t current; bool space, videoDone;
{
std::lock_guard<std::mutex> guard(p.lock);
current = p.videoGeneration; space = p.videos.size() < 2;
current = p.videoGeneration; space = p.videos.size() < 2; videoDone = p.videoEnded;
}
if (current != generation) {
avcodec_free_context(&decoder); av_packet_unref(packet); revision = 0; eosSent = false;
@@ -466,16 +466,22 @@ void StreamPlayerWindow::decodeVideo() {
DEBUG_DEBUG(DEBUG_CATEGORY_DEBUG, "desktop video generation id=%llu generation=%llu",
(unsigned long long)p.id, (unsigned long long)generation);
}
if (videoDone) {
std::unique_lock<std::mutex> guard(p.wakeLock);
p.wake.wait_for(guard, std::chrono::milliseconds(50), [&] { return !p.running || p.failed || p.wakeVersion != version; });
continue;
}
bool worked = false;
if (decoder && space) {
int64_t at = nowUs(); int result = avcodec_receive_frame(decoder, frame); codecTime(at);
{ std::lock_guard<std::mutex> guard(p.lock); if (generation != p.videoGeneration) continue; }
if (result == AVERROR_EOF) {
{ std::lock_guard<std::mutex> guard(p.lock);
if (generation != p.videoGeneration) continue;
p.videoEnded = true; p.videoBusy = false; }
DEBUG_INFO(DEBUG_CATEGORY_VIDEO, "desktop decoder drained id=%llu decoded=%llu discarded=%llu",
(unsigned long long)p.id, (unsigned long long)decoded, (unsigned long long)discarded);
p.notify(); break;
p.notify(); continue;
}
if (result < 0 && result != AVERROR(EAGAIN)) { fail(text("Stream video decoder failed")); break; }
if (result == 0) {
@@ -588,6 +594,7 @@ void StreamPlayerWindow::decodeVideo() {
}
if (space && decoder && (packet->size || (ending && !eosSent))) {
int64_t at = nowUs(); int result = avcodec_send_packet(decoder, packet->size ? packet : nullptr); codecTime(at);
{ std::lock_guard<std::mutex> guard(p.lock); if (generation != p.videoGeneration) continue; }
if (result == 0) {
worked = true;
{
@@ -608,7 +615,7 @@ void StreamPlayerWindow::decodeVideo() {
}
if (ending && !decoder && !packet->size) {
{ std::lock_guard<std::mutex> guard(p.lock); if (generation != p.videoGeneration) continue; p.videoEnded = true; }
p.notify(); break;
p.notify(); continue;
}
int64_t now = nowUs();
if (now - reportAt >= 1000000) {