fix(stepdown): restart the audio pipe around encoder changes
A quality step-down now closes the named audio pipe before stopping/flushing the pump, then opens a fresh server before restarting the pump. This prevents ffmpeg from waiting on the old audio input and avoids reconnecting to a broken pipe. EncoderRestartTests pins the audio-stop → video-stop → audio-start → video-start order. 616 tests green, clean build with 0 warnings.
This commit is contained in:
@@ -248,17 +248,24 @@ public sealed class FramePump : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>TASK 33: relaunch the pump and encoder at a new tier, over the same URL and audio pipe.
|
||||
/// <summary>TASK 33: relaunch the pump and encoder at a new tier, over the same URL and named audio pipe.
|
||||
///
|
||||
/// <para>Full stop + start rather than an encoder swap, deliberately: <see cref="StopAsync"/> awaits
|
||||
/// the loop and flushes the encoder, so no in-flight submit can land on a disposed process. A bare
|
||||
/// swap races exactly that and would fault the loop — which ends the broadcast, the one thing a
|
||||
/// quality step-down must never do. The cost is a short freeze, already accepted by the ladder.</para>
|
||||
/// quality step-down must never do. The audio pipe must be closed before the pump stops and freshly
|
||||
/// opened before it starts again; otherwise ffmpeg waits on the still-open audio input, then the new
|
||||
/// process tries to attach to a broken server. The cost is a short freeze, already accepted by the ladder.</para>
|
||||
/// </summary>
|
||||
public async Task<bool> ChangeEncoderAsync(CancellationToken cancellationToken = default)
|
||||
public async Task<bool> ChangeEncoderAsync(Action stopAudio, Action startAudio,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(stopAudio);
|
||||
ArgumentNullException.ThrowIfNull(startAudio);
|
||||
stopAudio();
|
||||
await StopAsync(cancellationToken);
|
||||
if (cancellationToken.IsCancellationRequested) return false;
|
||||
startAudio();
|
||||
await StartAsync(cancellationToken);
|
||||
return IsRunning;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user