Transitions: fade starts from the outgoing picture (was an instant cut)
The transition started with no from-frame, so BlendFrame returned the new scene at once. Start now requests a capture and the frame pump supplies its last output on the next tick. Test: TransitionFadeTests. Docs: ai.md, TASKS.md. Not pushed.
This commit is contained in:
@@ -32,6 +32,7 @@ public sealed class FramePump : IDisposable
|
||||
private readonly Func<VideoFrame?>? _alertTicker;
|
||||
private readonly Func<VideoFrame?>? _brandFlash;
|
||||
private readonly TransitionService? _transition;
|
||||
private VideoFrame? _lastOutput;
|
||||
private readonly SceneGraph? _sceneGraph;
|
||||
private readonly SceneCompositor _compositor = new();
|
||||
|
||||
@@ -497,6 +498,9 @@ public sealed class FramePump : IDisposable
|
||||
socialBarTicks += sw.ElapsedTicks;
|
||||
|
||||
VideoFrame frame;
|
||||
if (_transition is { CaptureRequested: true } capture && _lastOutput != null)
|
||||
capture.SupplyFromFrame(new VideoFrame(_lastOutput.Width, _lastOutput.Height,
|
||||
(byte[])_lastOutput.BgraPixels.Clone()));
|
||||
var scratchSize = compositorOptions.SourceRectWidth
|
||||
* compositorOptions.SourceRectHeight * 4;
|
||||
renderSw.Restart();
|
||||
@@ -567,6 +571,7 @@ public sealed class FramePump : IDisposable
|
||||
// tick's buffers are recyclable once the enqueue snapshot them.
|
||||
// The free-list Contains guard keeps the Cut path (BlendFrame
|
||||
// returns toFrame itself, aliasing scratch) safe.
|
||||
_lastOutput = frame;
|
||||
ReleaseScratch(frame.BgraPixels);
|
||||
ReleaseScratch(scratch);
|
||||
|
||||
|
||||
@@ -45,12 +45,23 @@ public sealed class TransitionService
|
||||
/// </summary>
|
||||
public VideoFrame? FromFrame { get; private set; }
|
||||
|
||||
/// <summary>True when a transition started without its "from" picture; the frame pump
|
||||
/// supplies the outgoing program frame on its next tick via <see cref="SupplyFromFrame"/>.</summary>
|
||||
public bool CaptureRequested { get; private set; }
|
||||
|
||||
public void SupplyFromFrame(VideoFrame frame)
|
||||
{
|
||||
FromFrame = frame;
|
||||
CaptureRequested = false;
|
||||
}
|
||||
|
||||
/// <summary>Begin a transition. Caller should capture FromFrame from the current LiveScene render.</summary>
|
||||
public void Start(TransitionType type, double durationMs, VideoFrame? fromFrame)
|
||||
{
|
||||
CurrentType = type;
|
||||
DurationMs = durationMs > 0 ? durationMs : DefaultDurationMs;
|
||||
FromFrame = fromFrame;
|
||||
CaptureRequested = fromFrame == null && type != TransitionType.Cut;
|
||||
ElapsedMs = 0;
|
||||
Active = true;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user