From 3efc34565a58523299a32069186467972012b491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Kr=C3=A4mer?= Date: Wed, 7 Jul 2021 20:16:14 +0200 Subject: [PATCH] Support cancellation token for cancelling FFMPEG processes --- FFMpegCore.Test/VideoTest.cs | 60 ++++++++++++++++++++ FFMpegCore/FFMpeg/FFMpegArgumentProcessor.cs | 5 ++ 2 files changed, 65 insertions(+) diff --git a/FFMpegCore.Test/VideoTest.cs b/FFMpegCore.Test/VideoTest.cs index 149dabd..2831084 100644 --- a/FFMpegCore.Test/VideoTest.cs +++ b/FFMpegCore.Test/VideoTest.cs @@ -12,6 +12,7 @@ using FFMpegCore.Arguments; using FFMpegCore.Exceptions; using FFMpegCore.Pipes; +using System.Threading; namespace FFMpegCore.Test { @@ -612,5 +613,64 @@ public async Task Video_Cancel_Async_With_Timeout() Assert.AreEqual("h264", outputInfo.PrimaryVideoStream.CodecName); Assert.AreEqual("aac", outputInfo.PrimaryAudioStream!.CodecName); } + + [TestMethod, Timeout(10000)] + public async Task Video_Cancel_CancellationToken_Async() + { + var outputFile = new TemporaryFile("out.mp4"); + + var cts = new CancellationTokenSource(); + + var task = FFMpegArguments + .FromFileInput("testsrc2=size=320x240[out0]; sine[out1]", false, args => args + .WithCustomArgument("-re") + .ForceFormat("lavfi")) + .OutputToFile(outputFile, false, opt => opt + .WithAudioCodec(AudioCodec.Aac) + .WithVideoCodec(VideoCodec.LibX264) + .WithSpeedPreset(Speed.VeryFast)) + .CancellableThrough(cts.Token) + .ProcessAsynchronously(false); + + await Task.Delay(300); + cts.Cancel(); + + var result = await task; + + Assert.IsFalse(result); + } + + [TestMethod, Timeout(10000)] + public async Task Video_Cancel_CancellationToken_Async_With_Timeout() + { + var outputFile = new TemporaryFile("out.mp4"); + + var cts = new CancellationTokenSource(); + + var task = FFMpegArguments + .FromFileInput("testsrc2=size=320x240[out0]; sine[out1]", false, args => args + .WithCustomArgument("-re") + .ForceFormat("lavfi")) + .OutputToFile(outputFile, false, opt => opt + .WithAudioCodec(AudioCodec.Aac) + .WithVideoCodec(VideoCodec.LibX264) + .WithSpeedPreset(Speed.VeryFast)) + .CancellableThrough(cts.Token, 10000) + .ProcessAsynchronously(false); + + await Task.Delay(300); + cts.Cancel(); + + var result = await task; + + var outputInfo = await FFProbe.AnalyseAsync(outputFile); + + Assert.IsTrue(result); + Assert.IsNotNull(outputInfo); + Assert.AreEqual(320, outputInfo.PrimaryVideoStream!.Width); + Assert.AreEqual(240, outputInfo.PrimaryVideoStream.Height); + Assert.AreEqual("h264", outputInfo.PrimaryVideoStream.CodecName); + Assert.AreEqual("aac", outputInfo.PrimaryAudioStream!.CodecName); + } } } diff --git a/FFMpegCore/FFMpeg/FFMpegArgumentProcessor.cs b/FFMpegCore/FFMpeg/FFMpegArgumentProcessor.cs index 67607af..060ffc3 100644 --- a/FFMpegCore/FFMpeg/FFMpegArgumentProcessor.cs +++ b/FFMpegCore/FFMpeg/FFMpegArgumentProcessor.cs @@ -50,6 +50,11 @@ public FFMpegArgumentProcessor CancellableThrough(out Action cancel, int timeout cancel = () => CancelEvent?.Invoke(this, timeout); return this; } + public FFMpegArgumentProcessor CancellableThrough(CancellationToken token, int timeout = 0) + { + token.Register(() => CancelEvent?.Invoke(this, timeout)); + return this; + } public bool ProcessSynchronously(bool throwOnError = true, FFOptions? ffMpegOptions = null) { using var instance = PrepareInstance(ffMpegOptions ?? GlobalFFOptions.Current, out var cancellationTokenSource);