Skip to content

Conversation

@irvingoujAtDevolution
Copy link
Contributor

@irvingoujAtDevolution irvingoujAtDevolution commented Jan 19, 2026

Fixes session shadowing playback stalls that occur when the video re-encoding pipeline falls behind real-time.

The main fix is an encoding strategy change: previously every re-encoded frame was force-keyframed, which is extremely CPU-intensive. Now only the first frame after the cut point is force-keyframed, and subsequent frames use normal inter-frame prediction, dramatically reducing encoder workload. Pre-cut-point frames are now decode-only instead of running the full encode pipeline and discarding the output. Encode duration is also derived from actual frame timestamps instead of a hardcoded value.

On top of this, the streamer adaptively skips encoding when falling behind real-time as a safety net, and the shadow player correctly seeks to the live edge using buffered ranges instead of seekable ranges.

Issue: DGW-341

@github-actions
Copy link

Let maintainers know that an action is required on their side

  • Add the label release-required Please cut a new release (Devolutions Gateway, Devolutions Agent, Jetsocat, PowerShell module) when you request a maintainer to cut a new release (Devolutions Gateway, Devolutions Agent, Jetsocat, PowerShell module)

  • Add the label release-blocker Follow-up is required before cutting a new release if a follow-up is required before cutting a new release

  • Add the label publish-required Please publish libraries (`Devolutions.Gateway.Utils`, OpenAPI clients, etc) when you request a maintainer to publish libraries (Devolutions.Gateway.Utils, OpenAPI clients, etc.)

  • Add the label publish-blocker Follow-up is required before publishing libraries if a follow-up is required before publishing libraries

@irvingoujAtDevolution irvingoujAtDevolution force-pushed the video-streamer-performance branch 3 times, most recently from c0c1482 to 55f6233 Compare February 3, 2026 22:05
@irvingoujAtDevolution irvingoujAtDevolution changed the title video streamer performance perf(video-streamer): add benchmarks and optimize re-encoding pipeline Feb 3, 2026
@irvingoujAtDevolution irvingoujAtDevolution marked this pull request as ready for review February 3, 2026 22:09
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds diagnostics, tests, and benchmarks around the WebM re-encoding pipeline to reproduce and measure the “progress stall” symptom and validate timeline correctness for live session playback.

Changes:

  • Introduces end-to-end correctness and performance tests for webm_stream, including live-growing input simulation and VPX-only reproductions of keyframe-related stalls.
  • Adds gated perf-diagnostics logging and statistics around the re-encoding and streaming path (VPX encoder/decoder, tag handling, and channel writer).
  • Provides a bench_support module and a Criterion benchmark (vpx_reencode) plus documentation and tooling (README, Justfile, Cargo features) for running targeted performance measurements.

Reviewed changes

Copilot reviewed 16 out of 18 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
crates/video-streamer/tests/webm_stream_perf.rs Adds an ignored perf test that simulates attach-at-20s on a growing WebM, writes output to disk, and asserts a low media-vs-wall-time ratio to reproduce the “progress stall” behavior.
crates/video-streamer/tests/webm_stream_correctness.rs Adds a suite of ignored async tests to validate timeline reset to 0, monotonic/simpleblock progress, metadata behavior on Start/Pull, EOF pause/resume handling, slow client behavior, and client disconnect semantics for webm_stream.
crates/video-streamer/tests/vpx_kf_spike_repro_first_kf_only.rs Adds a VPX-level control experiment that force-keyframes only the first post-cut frame to compare encode performance vs. the full forced-keyframe scenario.
crates/video-streamer/tests/vpx_kf_spike_repro.rs Adds a minimal VPX-only reproduction of the progress stall by continuously force-keyframing frames after a cut at ~20s.
crates/video-streamer/tests/support/mod.rs Introduces shared test infrastructure: in-memory websocket, live file writer, stream harness for webm_stream, global semaphore, XMF initialization, and WebM timestamp extraction helpers.
crates/video-streamer/tests/common/vpx_kf_spike.rs Adds common helpers for VPX tests to parse stream config and collect per-frame timestamps/keyframe flags for cut-point calculations.
crates/video-streamer/tests/common/mod.rs Re-exports the vpx_kf_spike helpers for use in VPX-related tests.
crates/video-streamer/src/streamer/tag_writers.rs Adds perf-logging around VPX encoder/decoder construction and re-encoding, tracks per-frame timing and stream realtime ratio behind a perf-diagnostics feature, and enriches error handling (including channel-closed detection) in CutClusterWriter.
crates/video-streamer/src/streamer/mod.rs Switches some debug!/trace! logging to perf_debug!/perf_trace! for header logging and EOF retry loops, tying them into the new diagnostics feature gate.
crates/video-streamer/src/streamer/iter.rs Adds perf_trace!/perf_debug! logging for keyframe discovery and rollback operations to aid debugging cut-point selection.
crates/video-streamer/src/streamer/channel_writer.rs Extends ChannelWriter and ChannelWriterReceiver with optional atomic counters and perf logging for writes/reads and total bytes, plus more informative diagnostics on channel closure.
crates/video-streamer/src/lib.rs Defines perf_trace! and perf_debug! macros gated by the perf-diagnostics feature, re-exports core streaming types, and exposes the new bench_support module under a bench feature.
crates/video-streamer/src/bench_support.rs Adds reusable helpers to re-encode the first N tags of a WebM stream (or until a wall-clock deadline), returning stats on tags, frames, media span, and bytes written for use in benchmarks.
crates/video-streamer/benches/vpx_reencode.rs Introduces a Criterion benchmark that repeatedly re-encodes the first 500 tags of a test WebM, with optional verbose stdout logging and per-iteration timeouts to bound work.
crates/video-streamer/README.md Documents prerequisites (XMF, environment vars), how to run correctness tests and ignored tests, how to enable perf-diagnostics, and how to run the new benchmarks with bench/verbose options.
crates/video-streamer/Cargo.toml Adds perf-diagnostics and bench features, the criterion dev-dependency, and registers the vpx_reencode bench target without a harness.
Justfile Adds a Windows/PowerShell-oriented test recipe (plus test-streamer alias) to run video-streamer correctness tests with logging and an isolated target directory.
Cargo.lock Updates the lockfile to include Criterion and its transitive dependencies, as well as other version bumps consistent with the new dev tooling.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Member

@CBenoit CBenoit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving so you can merge on your end

@CBenoit
Copy link
Member

CBenoit commented Feb 5, 2026

@irvingoujAtDevolution Before merging, update the PR into something more proper to be in the changelog (e.g.: perf(dgw): improve performance of session shadowing).

irvingoujAtDevolution and others added 7 commits February 9, 2026 15:11
…of seekable

The catch-up logic used `duration - currentTime > 5` with `seekable.end(0)`,
which threw IndexSizeError on every chunk when seekable ranges were empty
(early stream). Switch to `buffered` ranges which are always reliable and
don't depend on duration being finite.

Also add debug diagnostic logging for chunk appends, sourceBuffer state,
and endOfStream transitions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ming

When re-encoding 4K content, the VPX encode pipeline cannot keep up with
real-time (ratio plateaus at ~0.78). This adds adaptive frame skipping:
frames are decoded (to maintain the P-frame reference chain) but only
encoded when the realtime ratio is >= 1.0. This simple bang-bang control
self-regulates — skipping speeds up processing, pushing ratio above 1.0,
which resumes encoding until ratio drops again.

Verified on 3840x2400 VP9: ratio ramps from 0.065 to ~1.0 in ~7 seconds
and stays near real-time for the full session. No skipping occurs for
lower resolutions that already encode in real-time.

Also adds an `adaptive_frame_skip` config knob (default: true) to allow
disabling the feature.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove local path overrides for cadeau and xmf-sys, switching to the
published crates.io versions. Also updates other transitive dependencies.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…8 to u64 millis

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@irvingoujAtDevolution irvingoujAtDevolution changed the title perf(video-streamer): add benchmarks and optimize re-encoding pipeline perf(dgw): improve real-time performance of session shadowing Feb 11, 2026
@irvingoujAtDevolution irvingoujAtDevolution enabled auto-merge (squash) February 11, 2026 20:25
@irvingoujAtDevolution irvingoujAtDevolution merged commit ea2e6a8 into master Feb 11, 2026
40 checks passed
@irvingoujAtDevolution irvingoujAtDevolution deleted the video-streamer-performance branch February 11, 2026 20:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants