perf(video): move tier scaling to ffmpeg

The frame pump now submits crop-sized BGRA frames; FFmpeg scales them to final tier dimensions. Bundled scaler benchmark: 300 608x1080 to 1080x1920 frames in 0.435s (scaler-only).

Reference: https://ffmpeg.org/ffmpeg-filters.html#scale-1
This commit is contained in:
2026-11-04 10:52:35 -08:00
parent 76e8c22815
commit 6310f50c27
11 changed files with 93 additions and 47 deletions
+5 -5
View File
@@ -1,11 +1,11 @@
namespace ytLive.Services.Compositor;
/// <summary>
/// Where the compositor draws from (the active quality tier's output rect over the
/// 1920×1080 master) and at what size. 16:9 tiers = the full master 1:1; the vertical
/// 9:16 tier = the centered 607×1080 crop scaled up to 1080×1920. The source rect is
/// integer-aligned — MainViewModel's <c>OutputRectX</c> can be 656.5, so the caller
/// rounds before building these options.
/// Where the compositor draws from (the active quality tier's crop over the
/// 1920×1080 master) and the size of the BGRA frame it sends to the encoder. The
/// compositor frame is the crop itself; FFmpeg scales it to the selected output
/// dimensions. The source rect is integer-aligned — MainViewModel's
/// <c>OutputRectX</c> can be 656.5, so the caller rounds before building these options.
/// </summary>
public sealed class CompositorOptions
{
+4 -3
View File
@@ -6,10 +6,11 @@ using ytLive.Models;
namespace ytLive.Services.Compositor;
/// <summary>
/// The output compositor: renders a scene into the encoder's master frame (tightly-packed
/// The output compositor: renders a scene into the encoder's raw input frame (tightly-packed
/// BGRA8 <see cref="VideoFrame"/>) exactly as the XAML preview renders it, minus the
/// editing chrome (SelectionOverlay, DimRects, badge, placeholder). The preview stays the
/// editing view; this is the output view — see TASKS.md "Ship step 1 — Scene compositor".
/// editing chrome (SelectionOverlay, DimRects, badge, placeholder). FFmpeg scales that frame
/// to the selected output dimensions. The preview stays the editing view; this is the output
/// view — see TASKS.md "Ship step 1 — Scene compositor".
///
/// Frame sources are supplied by a <see cref="Func{SceneElement, VideoFrame}"/> resolver
/// (the caller maps webcam → DeviceId, images → AssetId, background → CaptureKey), keeping