8f490102ee
Adds the codec-agnostic decoder half of the media source. Spawns ffmpeg with -f rawvideo -pix_fmt bgra (reusing the already-shipped ffmpeg via IFfmpegLocator) and drains the raw BGRA stdout pipe into VideoFrames. - Services/RawVideoFrameReader.cs: pure rawvideo BGRA stream -> frames (partial reads kept across Feed; no ffmpeg needed to test) - Services/IDecodeProcess.cs + FfmpegDecodeProcess.cs: binary-stdout subprocess seam, mirror of the encoder's IEncoderProcess - Services/MediaVideoSource.cs: owns the decode, raises FrameReady/Completed - MediaVideoSourceTests: 3 pure reader + 1 integration (fake decode process through the real source loop, frames in order) Reference (external scan): ffmpeg rawvideo pipe decode is the canonical codec-agnostic frame feeds pattern (ffmpeg docs -f rawvideo; how OBS/media pipelines push frames to a compositor). Verified: 4/4 tests, build 0 warnings. Native-FPS pacing + resolver/compositor wiring are the next slice.
37 lines
1.1 KiB
C#
37 lines
1.1 KiB
C#
using System.Diagnostics;
|
|
using System.IO;
|
|
|
|
namespace ytLive.Services;
|
|
|
|
/// <summary>
|
|
/// The real <see cref="IDecodeProcess"/>: a <see cref="Process"/> with stdout
|
|
/// redirected as raw bytes for reading <c>rawvideo</c> frames. Constructed by
|
|
/// <see cref="MediaVideoSource"/> for the media-file decoder subprocess.
|
|
/// </summary>
|
|
public sealed class FfmpegDecodeProcess : IDecodeProcess
|
|
{
|
|
private readonly Process _process;
|
|
|
|
public FfmpegDecodeProcess() => _process = new Process { EnableRaisingEvents = true };
|
|
|
|
public void Start(ProcessStartInfo startInfo)
|
|
{
|
|
_process.StartInfo = startInfo;
|
|
_process.Start();
|
|
}
|
|
|
|
public Stream StandardOutput => _process.StandardOutput.BaseStream;
|
|
|
|
public bool HasExited => _process.HasExited;
|
|
public int ExitCode => _process.ExitCode;
|
|
public void Kill()
|
|
{
|
|
if (!_process.HasExited) _process.Kill();
|
|
}
|
|
|
|
public Task WaitForExitAsync(CancellationToken cancellationToken = default)
|
|
=> _process.WaitForExitAsync(cancellationToken);
|
|
|
|
public void Dispose() => _process.Dispose();
|
|
}
|