From a056b2c2627831c1cd2c43a32e09915dc8fa548b Mon Sep 17 00:00:00 2001 From: evgeny Date: Mon, 26 Oct 2026 09:50:34 +0100 Subject: [PATCH] Describe publisher packing budgets and queued audio rejection --- doc/stream.txt | 9 +++++++++ src/stream/stream_publisher.c | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/doc/stream.txt b/doc/stream.txt index 7165ecec..a4a18a04 100644 --- a/doc/stream.txt +++ b/doc/stream.txt @@ -8,6 +8,9 @@ stream_block.h, stream_source.h и stream_media.h; остальные разде закрытие handles/выдач, изоляцию каналов и повторное разрешение участия. Полный аудит оставшихся разделов ещё не завершён. Подтверждения, архитектура исправления и результаты проверок — doc/stream_audit_findings.txt. +Дефект publisher_block устранён: помещающийся Opus уходит в отдельную аудиопачку, +ожидающее видео получает следующий слот actor. Штатный test_stream_publisher +проверяет 23 сценария границ, продвижения треков и OPENING/FIN; раздел 7 отчёта. 1. Цель и принятые решения @@ -846,6 +849,12 @@ Android: UI не сохраняет borrowed inst/ua. Idle без pending data не будит мобильное ядро. - TX<=2MiB/128 records, не более 250ms ожидания. Actor публикует <=2 пачек за вызов, неполную пачку объединяет с аудио/видео до 20ms; продолжение работы через timer 5ms. + Opus целиком занимает header32 + audio descriptor16 + payload; точное заполнение допустимо. + Без ожидающего видео резерв под video descriptor отсутствует. Обычная смешанная пачка + сохраняет место под описание и непустой фрагмент видео. Если первый Opus помещается только отдельно, + второй слот того же actor отдаётся видео без ожидания сборки неполной пачки. + feed=1 означает копирование в очередь. Actor после определения FEC-ёмкости при open удаляет Opus, + не помещающийся даже отдельно, с WARN (ID, PTS, bytes, max, capacity), не блокируя следующие записи. При video pressure отбрасываются целые ожидающие кадры, P-кадры запрещены до нового KEY. Кодировщик получает отказ admission и запрашивает KEY с ограничением частоты 500ms. - RX: stream_viewers держит отдельный handle/cursor, demand, status и ограниченный owned батч на session ID. diff --git a/src/stream/stream_publisher.c b/src/stream/stream_publisher.c index f11ecc99..8b7173e1 100644 --- a/src/stream/stream_publisher.c +++ b/src/stream/stream_publisher.c @@ -242,8 +242,8 @@ static void publisher_process(void *arg) { uint64_t oldest = p->video.head ? p->video.head->created : p->audio.head->created; if (p->audio.head && p->audio.head->created < oldest) oldest = p->audio.head->created; int immediate = p->video.head && p->video.head->key; - if (!p->stopping && !immediate && !video_turn && pending + STREAM_MEDIA_HEADER_SIZE + STREAM_MEDIA_VIDEO_SIZE < p->capacity - && now - oldest < 20000) break; + if (!p->stopping && !immediate && !video_turn + && pending + STREAM_MEDIA_HEADER_SIZE + STREAM_MEDIA_VIDEO_SIZE < p->capacity && now - oldest < 20000) break; int result = publisher_block(p, &video_turn); if (result < 0) { DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "publisher block failed result=%d", result); publisher_close(p, STREAM_CLOSE_FAILED); break; } }