fix(encode/windows): a stale PUNKTFUNK_ENCODER pin no longer wedges a conflicting GPU selection
On a hybrid box, picking a GPU in the web console whose vendor contradicts a host.env PUNKTFUNK_ENCODER pin produced an unrecoverable session: the pin won backend selection while the adapter followed the console, the wrong-vendor encoder failed deterministically at submit, the reset ladder burned its 5 in-place rebuilds on it, and the client reconnected into the identical wall forever (~10 s per cycle, no visible reason). Three legs: - windows_resolved_backend() now reconciles: a hardware pin whose vendor contradicts the selected GPU is overridden by the adapter-derived backend (capture + encode share one adapter, so honoring the pin can only fail); open_video warns loudly when a pin loses. The reconciliation is a pure, unit-tested table (resolve_windows_backend). - the QSV wrong-adapter bind is typed TerminalEncoderError, and the stream loop's reset ladder ends the session immediately on it instead of feeding a deterministic config error 5 futile rebuilds. - the un-pinned path was already correct (verified on-glass: NVIDIA preference + no pin = stable AV1 10-bit HDR on NVENC), so the override simply takes the conflict case onto that path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2329,6 +2329,19 @@ pub(super) fn virtual_stream(ctx: SessionContext, prepared: Option<PreparedDispl
|
||||
// assign next. The RFI backends pin their frame numbering to it.
|
||||
let wire_index = au_seq.wrapping_add(inflight.len() as u32);
|
||||
if let Err(e) = enc.submit_indexed(&frame, wire_index) {
|
||||
// A typed-terminal error is a deterministic configuration failure — the identical
|
||||
// wall on every attempt, so rebuilds can't help. End the session at once with the
|
||||
// carried cause (observed: a stale PUNKTFUNK_ENCODER pin vs. the selected adapter
|
||||
// burned all 5 rebuilds per connect while the client reconnected forever).
|
||||
if e.downcast_ref::<crate::encode::TerminalEncoderError>()
|
||||
.is_some()
|
||||
{
|
||||
tracing::error!(
|
||||
error = %format!("{e:#}"),
|
||||
"encoder failed with a deterministic configuration error — ending the video \
|
||||
session without rebuild attempts (see the error for the remedy)");
|
||||
return Err(e).context("encoder submit");
|
||||
}
|
||||
// The input half of an encode stall: once the driver stops draining AUs, libavcodec's
|
||||
// one-frame buffer fills and avcodec_send_frame starts failing (EAGAIN) — the same
|
||||
// wedge the watchdog below catches, seen from submit. Rebuild the encoder in place
|
||||
|
||||
Reference in New Issue
Block a user