namespace TeamsISO.Engine.Pipeline;
///
/// Tap point for per-ISO output recording. Each can be
/// wired with one recorder; when present, every that
/// flows from to is also fed
/// to the recorder for persistence to disk.
///
/// Lifecycle:
/// 1. is called once when the pipeline starts (or restarts).
/// 2. is called for every processed frame, in order.
/// 3. is called once when the pipeline stops or fails.
///
/// Implementations must be tolerant of out-of-order calls (Close before Open,
/// double Close, WriteFrame after Close) — the supervisor's restart logic can
/// race in unusual ways. The simplest correct implementation is to track an
/// _isOpen flag and short-circuit when not open.
///
public interface IRecorderSink : IAsyncDisposable
{
///
/// Open the underlying file/encoder and prepare to receive frames. Width/Height
/// match the pipeline's normalized output resolution; FPS is the target framerate
/// (incoming frames may arrive with timing jitter, but the recorder writes at the
/// nominal rate for downstream playback consistency).
///
/// Used to derive the output filename.
/// Directory under which the recording is created.
/// Frame width in pixels.
/// Frame height in pixels.
/// Nominal framerate.
void Open(string participantDisplayName, string outputDirectory, int width, int height, double fps);
///
/// Write one processed frame. Implementations should not block — if encoding is
/// expensive, queue the frame to a worker thread and return promptly. Returning
/// false means the recorder dropped the frame (disk full, queue overflow); the
/// pipeline carries on regardless so a recorder failure never kills the live ISO.
///
bool WriteFrame(ProcessedFrame frame);
///
/// Flush and finalize the output. Idempotent.
///
void Close();
/// True between successful and .
bool IsRecording { get; }
///
/// Drop a timestamped marker into the recording. Used by the operator to
/// chapter a recording in real time — "host intro starts here", "guest
/// answer", etc. — so post-production can jump to the right moment without
/// scrubbing through the raw stream. The label is free-form; an empty
/// label means "unnamed marker." No-op when not recording.
///
void AddMarker(string label);
}