Files
LlamaCasty/Services/IMediaFrameSource.cs
T
gramps 881addb5b4 TASK 21 slice 3: loop control in MediaVideoSource (process factory + Loop flag)
- IMediaFrameSource gains bool Looping.
- MediaVideoSource ctor takes Func<IDecodeProcess> processFactory instead of a
  single IDecodeProcess: a System.Diagnostics.Process can't be re-Start()ed, so
  each loop pass creates a fresh decoder. Decode wrapped in do-while(Looping):
  restart on natural EOF instead of raising Completed.
- Production wiring (MainViewModel media factory): passes the process factory
  AND FfmpegFrameRateProbe -- closes the slice-2b gap where production had no
  probe and therefore no pacing.
- Tests: loop test (single frame re-emits across passes, Completed only when
  loop cleared); fakes updated for the new interface member. Media tests 12/12,
  build 0 warnings.

Wiring Source.MediaIsLooping into the flag needs a manager-level per-path loop
provider -> lands with the UI-picker (acquisition) slice.

Derivative reference: looping media by restarting decode on EOF, standard in
playback/overlay tooling (OBS media source repeat).
2026-08-31 19:52:10 -07:00

27 lines
1.0 KiB
C#

namespace ytLive.Services;
/// <summary>
/// TASK 21: a media file decoder exposed to <see cref="MediaVideoSourceManager"/>.
/// Mirrors <c>IScreenCaptureSource</c>/<c>ICameraFrameSource</c> so the manager
/// (and tests) treat a local video file like any other frame source: start/stop
/// and a per-frame <see cref="FrameAvailable"/> event consumers coalesce.
/// </summary>
public interface IMediaFrameSource : IDisposable
{
string Key { get; }
/// <summary>When true, the decoder restarts from the beginning on natural EOF
/// instead of raising <see cref="Completed"/> (used for BRB/starting-soon loops).</summary>
bool Looping { get; set; }
/// <summary>Raised (on a worker thread) for each decoded frame.</summary>
event Action<VideoFrame>? FrameAvailable;
/// <summary>Raised when the file finishes decoding (natural EOF) — not raised
/// while <see cref="Looping"/> is true.</summary>
event Action? Completed;
Task StartAsync(CancellationToken cancellationToken = default);
Task StopAsync();
}