diff --git a/FFMpegCore.Test/ArgumentBuilderTest.cs b/FFMpegCore.Test/ArgumentBuilderTest.cs
index 18a8c7d..daa3eda 100644
--- a/FFMpegCore.Test/ArgumentBuilderTest.cs
+++ b/FFMpegCore.Test/ArgumentBuilderTest.cs
@@ -192,6 +192,17 @@ public void Builder_BuildString_Transpose()
Assert.AreEqual("-i \"input.mp4\" -vf \"transpose=2\" \"output.mp4\"", str);
}
+ [TestMethod]
+ public void Builder_BuildString_Mirroring()
+ {
+ var str = FFMpegArguments.FromFileInput("input.mp4")
+ .OutputToFile("output.mp4", false, opt => opt
+ .WithVideoFilters(filterOptions => filterOptions
+ .Mirror(Mirroring.Horizontal)))
+ .Arguments;
+ Assert.AreEqual("-i \"input.mp4\" -vf \"hflip\" \"output.mp4\"", str);
+ }
+
[TestMethod]
public void Builder_BuildString_TransposeScale()
{
diff --git a/FFMpegCore.sln b/FFMpegCore.sln
index 27eab0a..7a27980 100644
--- a/FFMpegCore.sln
+++ b/FFMpegCore.sln
@@ -1,13 +1,13 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.28307.329
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31005.135
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FFMpegCore", "FFMpegCore\FFMpegCore.csproj", "{19DE2EC2-9955-4712-8096-C22EF6713E4F}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FFMpegCore", "FFMpegCore\FFMpegCore.csproj", "{19DE2EC2-9955-4712-8096-C22EF6713E4F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FFMpegCore.Test", "FFMpegCore.Test\FFMpegCore.Test.csproj", "{F20C8353-72D9-454B-9F16-3624DBAD2328}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FFMpegCore.Examples", "FFMpegCore.Examples\FFMpegCore.Examples.csproj", "{3125CF91-FFBD-4E4E-8930-247116AFE772}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FFMpegCore.Examples", "FFMpegCore.Examples\FFMpegCore.Examples.csproj", "{3125CF91-FFBD-4E4E-8930-247116AFE772}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/FFMpegCore/FFMpeg/Arguments/SetMirroringArgument.cs b/FFMpegCore/FFMpeg/Arguments/SetMirroringArgument.cs
new file mode 100644
index 0000000..f042f77
--- /dev/null
+++ b/FFMpegCore/FFMpeg/Arguments/SetMirroringArgument.cs
@@ -0,0 +1,32 @@
+using FFMpegCore.Enums;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace FFMpegCore.Arguments
+{
+ public class SetMirroringArgument : IVideoFilterArgument
+ {
+ public SetMirroringArgument(Mirroring mirroring)
+ {
+ Mirroring = mirroring;
+ }
+
+ public Mirroring Mirroring { get; set; }
+
+ public string Key => string.Empty;
+
+ public string Value
+ {
+ get
+ {
+ return Mirroring switch
+ {
+ Mirroring.Horizontal => "hflip",
+ Mirroring.Vertical => "vflip",
+ _ => throw new ArgumentOutOfRangeException(nameof(Mirroring))
+ };
+ }
+ }
+ }
+}
diff --git a/FFMpegCore/FFMpeg/Arguments/VideoFiltersArgument.cs b/FFMpegCore/FFMpeg/Arguments/VideoFiltersArgument.cs
index f7fef93..fa4ae1e 100644
--- a/FFMpegCore/FFMpeg/Arguments/VideoFiltersArgument.cs
+++ b/FFMpegCore/FFMpeg/Arguments/VideoFiltersArgument.cs
@@ -17,12 +17,20 @@ public VideoFiltersArgument(VideoFilterOptions options)
public string Text => GetText();
- public string GetText()
+ private string GetText()
{
if (!Options.Arguments.Any())
throw new FFMpegArgumentException("No video-filter arguments provided");
- return $"-vf \"{string.Join(", ", Options.Arguments.Where(arg => !string.IsNullOrEmpty(arg.Value)).Select(arg => $"{arg.Key}={arg.Value.Replace(",", "\\,")}"))}\"";
+ var arguments = Options.Arguments
+ .Where(arg => !string.IsNullOrEmpty(arg.Value))
+ .Select(arg =>
+ {
+ var escapedValue = arg.Value.Replace(",", "\\,");
+ return string.IsNullOrEmpty(arg.Key) ? escapedValue : $"{arg.Key}={escapedValue}";
+ });
+
+ return $"-vf \"{string.Join(", ", arguments)}\"";
}
}
@@ -40,6 +48,7 @@ public class VideoFilterOptions
public VideoFilterOptions Scale(int width, int height) => WithArgument(new ScaleArgument(width, height));
public VideoFilterOptions Scale(Size size) => WithArgument(new ScaleArgument(size));
public VideoFilterOptions Transpose(Transposition transposition) => WithArgument(new TransposeArgument(transposition));
+ public VideoFilterOptions Mirror(Mirroring mirroring) => WithArgument(new SetMirroringArgument(mirroring));
public VideoFilterOptions DrawText(DrawTextOptions drawTextOptions) => WithArgument(new DrawTextArgument(drawTextOptions));
private VideoFilterOptions WithArgument(IVideoFilterArgument argument)
diff --git a/FFMpegCore/FFMpeg/Enums/Mirroring.cs b/FFMpegCore/FFMpeg/Enums/Mirroring.cs
new file mode 100644
index 0000000..5768163
--- /dev/null
+++ b/FFMpegCore/FFMpeg/Enums/Mirroring.cs
@@ -0,0 +1,8 @@
+namespace FFMpegCore.Enums
+{
+ public enum Mirroring
+ {
+ Vertical,
+ Horizontal
+ }
+}
diff --git a/FFMpegCore/FFMpegCore.csproj b/FFMpegCore/FFMpegCore.csproj
index 47b41d8..bf9e682 100644
--- a/FFMpegCore/FFMpegCore.csproj
+++ b/FFMpegCore/FFMpegCore.csproj
@@ -9,11 +9,9 @@
3.0.0.0
3.0.0.0
3.0.0.0
- - Fixes for RawVideoPipeSource hanging (thanks to max619)
-- Added .OutputToUrl(..) method for outputting to url using supported protocol (thanks to TFleury)
-- Improved timespan parsing (thanks to test-in-prod)
+ - Added support for mirroring video filter (thanks gorobvictor)
8
- 4.1.0
+ 4.2.0
MIT
Malte Rosenbjerg, Vlad Jerca, Max Bagryantsev
ffmpeg ffprobe convert video audio mediafile resize analyze muxing