58 lines
2.8 KiB
C#
58 lines
2.8 KiB
C#
namespace TeamsISO.Engine.Pipeline;
|
|
|
|
/// <summary>
|
|
/// Tap point for per-ISO output recording. Each <see cref="IsoPipeline"/> can be
|
|
/// wired with one recorder; when present, every <see cref="ProcessedFrame"/> that
|
|
/// flows from <see cref="FrameProcessor"/> to <see cref="NdiSender"/> is also fed
|
|
/// to the recorder for persistence to disk.
|
|
///
|
|
/// Lifecycle:
|
|
/// 1. <see cref="Open"/> is called once when the pipeline starts (or restarts).
|
|
/// 2. <see cref="WriteFrame"/> is called for every processed frame, in order.
|
|
/// 3. <see cref="Close"/> 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
|
|
/// <c>_isOpen</c> flag and short-circuit when not open.
|
|
/// </summary>
|
|
public interface IRecorderSink : IAsyncDisposable
|
|
{
|
|
/// <summary>
|
|
/// 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).
|
|
/// </summary>
|
|
/// <param name="participantDisplayName">Used to derive the output filename.</param>
|
|
/// <param name="outputDirectory">Directory under which the recording is created.</param>
|
|
/// <param name="width">Frame width in pixels.</param>
|
|
/// <param name="height">Frame height in pixels.</param>
|
|
/// <param name="fps">Nominal framerate.</param>
|
|
void Open(string participantDisplayName, string outputDirectory, int width, int height, double fps);
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
bool WriteFrame(ProcessedFrame frame);
|
|
|
|
/// <summary>
|
|
/// Flush and finalize the output. Idempotent.
|
|
/// </summary>
|
|
void Close();
|
|
|
|
/// <summary>True between successful <see cref="Open"/> and <see cref="Close"/>.</summary>
|
|
bool IsRecording { get; }
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
void AddMarker(string label);
|
|
}
|