Drain publisher while asynchronous microphone teardown completes
This commit is contained in:
1 parent
114c0b3e2f
commit
16e547d15d
2 files changed
+17
-8
No files matched your search
@@ -120,6 +120,9 @@ Android worker держит один рабочий input и один готов
|
||||
input buffer получает лишь для уже готовых данных и сразу возвращает codec.
|
||||
Первый decoded frame разрешает движение clock/audio. Будущий output ждёт PTS и
|
||||
приостанавливает новые video requests, сохраняя независимую обработку audio/control.
|
||||
Если первый доступный звук позже KEY, cursor отсчитывает стартовый audio lookahead от
|
||||
первого аудиопакета, сохраняя это основание неизменным. Opus/SoundTouch получает PCM до
|
||||
запуска audio clock; неподвижные часы не разрешают читать дальше этого ограниченного окна.
|
||||
PTS поданных кадров служат диагностике/проверке запаздывания, а не лимиту заполнения codec.
|
||||
Смена revision заменяет только video decoder и его измеренный защитный guard;
|
||||
GAP/EXPIRED начинают новую точку KEY. Нехватка сети сохраняет decoder references.
|
||||
@@ -145,10 +148,14 @@ Qt capture callback хранит только последний кадр, video
|
||||
вне GUI и hardware callbacks. Отдельные поколения источника и encoder позволяют менять
|
||||
видеокодек/bitrate/rotation без повторного выбора экрана в портале. Ошибки Qt capture
|
||||
обрабатываются через queued callback, чтобы не уничтожать backend из собственного callback.
|
||||
Сначала stop запрещает producers, закрывает Qt capture и подписку на аудиозахват, затем join workers,
|
||||
освобождает microphone lease и завершает публикацию через FIN с drain 2s.
|
||||
Stop запрещает producers, закрывает Qt capture и подписку на аудиозахват. Отдельный join worker
|
||||
дожидается полного выхода video/audio threads, включая native TLS Qt; GUI продолжает обрабатывать события.
|
||||
После join отправляется FIN с drain 2s; закрытие последнего микрофона может продолжаться параллельно.
|
||||
Microphone lease и owner сохраняются до завершения обоих путей. Новый start ждёт также FIN drain.
|
||||
При завершении приложения engine уничтожается до SoundManager и ядра; detach в uasync
|
||||
закрывает оставшийся publisher. Workers никогда не держат borrowed instance/handle.
|
||||
закрывает оставшийся publisher. Destructor ждёт workers в локальном event loop без пользовательского ввода,
|
||||
чтобы thread cleanup мог обратиться к GUI; start и внешние сигналы engine в это время запрещены.
|
||||
Workers никогда не держат borrowed instance/handle.
|
||||
Microphone lease публикации исключает call/recorder; рация согласует вход через `AudioCapture`.
|
||||
Одинаковый выбранный вход имеет одну аппаратную сессию и профиль трансляции. Разные входы независимы.
|
||||
Подключение/отключение рации не останавливает устройство трансляции: атомарный слот и счётчик readers
|
||||
|
||||
@@ -63,7 +63,7 @@ struct StreamPublishEngine::Impl {
|
||||
std::condition_variable wake;
|
||||
std::thread videoThread, audioThread, joinThread;
|
||||
std::atomic<bool> workersJoined{false}, videoExited{false}, audioExited{false};
|
||||
bool stopping = false, destroying = false;
|
||||
bool stopping = false, finSent = false, destroying = false;
|
||||
int64_t stopStarted = 0, stopReport = 0;
|
||||
std::atomic<bool> running{false}, muted{false};
|
||||
std::atomic<unsigned> audioDropped{0}, audioMissing{0};
|
||||
@@ -494,7 +494,7 @@ void StreamPublishEngine::publicationFailed(uint64_t id, const QString& error) {
|
||||
void StreamPublishEngine::stop() {
|
||||
if (!m->running.exchange(false)) return;
|
||||
int64_t started = monotonicUs();
|
||||
m->stopping = true; m->stopStarted = m->stopReport = started;
|
||||
m->stopping = true; m->finSent = false; m->stopStarted = m->stopReport = started;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_VIDEO, "desktop stop begin id=%llu video_stage=%s stage_age_ms=%lld converted=%llu encoded=%llu delivered=%llu",
|
||||
(unsigned long long)m->id, m->videoStage.load(), (long long)((started - m->videoStageAt.load()) / 1000),
|
||||
(unsigned long long)m->convertedFrames.load(), (unsigned long long)m->encodedFrames.load(),
|
||||
@@ -522,11 +522,13 @@ bool StreamPublishEngine::finishStop() {
|
||||
if (!m->workersJoined) return false;
|
||||
m->joinThread.join();
|
||||
}
|
||||
if (!m->finSent) {
|
||||
gui_stream_publish_stop(m->id); m->finSent = true;
|
||||
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "desktop workers stopped id=%llu elapsed_ms=%lld microphone_closing=%d; draining publisher",
|
||||
(unsigned long long)m->id, (long long)((monotonicUs() - m->stopStarted) / 1000), m_capture.closing());
|
||||
}
|
||||
if (m_capture.closing()) return false;
|
||||
m_microphone.release(); m->stopping = false;
|
||||
gui_stream_publish_stop(m->id);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_STREAM, "desktop capture stopped id=%llu elapsed_ms=%lld; draining publisher",
|
||||
(unsigned long long)m->id, (long long)((monotonicUs() - m->stopStarted) / 1000));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user