using System; using System.IO; using System.Linq; using System.Threading.Tasks; using Paca.Core.Media; using Xunit; namespace Paca.Tests.Media; public class HardwareTranscoderAndCastingExtremeRedTests { [Fact] public void BuildFfmpegTranscodeCommand_NullSpec_ThrowsArgumentNullException() { Assert.Throws(() => HardwareTranscoderStudio.BuildFfmpegTranscodeCommand("input.mp4", "output.mp4", null!)); } [Theory] [InlineData(null)] [InlineData("")] [InlineData(" ")] public void BuildFfmpegTranscodeCommand_NullOrWhitespaceInput_ThrowsArgumentException(string? invalidInput) { var spec = new TranscodePresetSpec(); Assert.Throws(() => HardwareTranscoderStudio.BuildFfmpegTranscodeCommand(invalidInput!, "output.mp4", spec)); } [Theory] [InlineData(null)] [InlineData("")] [InlineData(" ")] public void BuildFfmpegTranscodeCommand_NullOrWhitespaceOutput_ThrowsArgumentException(string? invalidOutput) { var spec = new TranscodePresetSpec(); Assert.Throws(() => HardwareTranscoderStudio.BuildFfmpegTranscodeCommand("input.mp4", invalidOutput!, spec)); } [Fact] public void BuildFfmpegTranscodeCommand_SameInputAndOutput_ThrowsInvalidOperationException() { var tempFile = Path.GetTempFileName(); try { var spec = new TranscodePresetSpec(); Assert.Throws(() => HardwareTranscoderStudio.BuildFfmpegTranscodeCommand(tempFile, tempFile, spec)); } finally { if (File.Exists(tempFile)) File.Delete(tempFile); } } [Fact] public void BuildFfmpegTranscodeCommand_QuotedPaths_StripsQuotesAndProducesValidArgs() { var spec = new TranscodePresetSpec { Backend = HardwareEncoderBackend.SoftwareCpu, Codec = VideoCodecTarget.H264 }; var args = HardwareTranscoderStudio.BuildFfmpegTranscodeCommand("\"C:\\input video.mp4\"", "\"C:\\out.mp4\"", spec); Assert.Equal("C:\\input video.mp4", args[1]); Assert.Equal("C:\\out.mp4", args.Last()); } [Fact] public void BuildFfmpegTranscodeCommand_NullOrEmptyAudioCodec_DefaultsToAac() { var spec = new TranscodePresetSpec { AudioCodec = " " }; var args = HardwareTranscoderStudio.BuildFfmpegTranscodeCommand("in.mkv", "out.mp4", spec); var aIndex = args.IndexOf("-c:a"); Assert.True(aIndex >= 0); Assert.Equal("aac", args[aIndex + 1]); } [Theory] [InlineData(HardwareEncoderBackend.NvidiaNvenc, VideoCodecTarget.AV1, "av1_nvenc")] [InlineData(HardwareEncoderBackend.NvidiaNvenc, VideoCodecTarget.HEVC_H265, "hevc_nvenc")] [InlineData(HardwareEncoderBackend.NvidiaNvenc, VideoCodecTarget.H264, "h264_nvenc")] [InlineData(HardwareEncoderBackend.IntelQsv, VideoCodecTarget.AV1, "av1_qsv")] [InlineData(HardwareEncoderBackend.IntelQsv, VideoCodecTarget.HEVC_H265, "hevc_qsv")] [InlineData(HardwareEncoderBackend.AmdAmf, VideoCodecTarget.AV1, "av1_amf")] [InlineData(HardwareEncoderBackend.AmdAmf, VideoCodecTarget.HEVC_H265, "hevc_amf")] [InlineData(HardwareEncoderBackend.SoftwareCpu, VideoCodecTarget.AV1, "libsvtav1")] [InlineData(HardwareEncoderBackend.SoftwareCpu, VideoCodecTarget.HEVC_H265, "libx265")] public void BuildFfmpegTranscodeCommand_Backends_ProducesCorrectVideoCodec( HardwareEncoderBackend backend, VideoCodecTarget codec, string expectedCodec) { var spec = new TranscodePresetSpec { Backend = backend, Codec = codec }; var args = HardwareTranscoderStudio.BuildFfmpegTranscodeCommand("in.mp4", "out.mp4", spec); var vIndex = args.IndexOf("-c:v"); Assert.True(vIndex >= 0); Assert.Equal(expectedCodec, args[vIndex + 1]); } [Fact] public void BuildFfmpegTranscodeCommand_NegativeBitrate_DoesNotEmitBitrateFlag() { var spec = new TranscodePresetSpec { TargetBitrateKbps = -100 }; var args = HardwareTranscoderStudio.BuildFfmpegTranscodeCommand("in.mp4", "out.mp4", spec); Assert.DoesNotContain("-b:v", args); } [Fact] public void WebRtcCastingEngine_TerminateSession_NullSessionId_ReturnsFalseWithoutThrowing() { var engine = new WebRtcCastingEngine(); var result = engine.TerminateSession(null!); Assert.False(result); } [Fact] public void WebRtcCastingEngine_TerminateSession_UnknownSessionId_ReturnsFalse() { var engine = new WebRtcCastingEngine(); var result = engine.TerminateSession("non-existent-uuid"); Assert.False(result); } [Theory] [InlineData(null)] [InlineData("")] [InlineData(" ")] public void WebRtcCastingEngine_CreateCastSession_NullOrWhitespaceDevice_DefaultsToDefaultDisplay(string? deviceName) { var engine = new WebRtcCastingEngine(); var session = engine.CreateCastSession(deviceName!); Assert.Equal("Default Display", session.TargetDeviceName); } [Fact] public void WebRtcCastingEngine_GetSession_WorksCorrectly() { var engine = new WebRtcCastingEngine(); Assert.Null(engine.GetSession(null!)); Assert.Null(engine.GetSession("unknown-id")); var created = engine.CreateCastSession("Living Room TV"); var found = engine.GetSession(created.SessionId); Assert.NotNull(found); Assert.Equal("Living Room TV", found.TargetDeviceName); } [Fact] public void WebRtcCastingEngine_GenerateOffer_InvalidDimensions_NormalizesDimensions() { var engine = new WebRtcCastingEngine(); var desc = engine.GenerateOffer(null!, width: -50, height: 0, fps: -1); Assert.Equal("offer", desc.Type); Assert.Contains("v=0", desc.Sdp); Assert.Contains("H264", desc.Sdp); } [Fact] public void WebRtcCastingEngine_ThreadSafety_ConcurrentCreateAndTerminate() { var engine = new WebRtcCastingEngine(); Parallel.For(0, 50, i => { var session = engine.CreateCastSession($"Device {i}"); Assert.NotNull(engine.GetSession(session.SessionId)); var terminated = engine.TerminateSession(session.SessionId); Assert.True(terminated); Assert.Null(engine.GetSession(session.SessionId)); }); Assert.Equal(0, engine.ActiveSessionsCount); } }