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