mirror of
https://github.com/rosenbjerg/FFMpegCore.git
synced 2025-12-15 02:25:44 +00:00
Compare commits
21 commits
f919a05d43
...
bbdbe5592a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bbdbe5592a | ||
|
|
8b8701ef44 | ||
|
|
abf2ab5ee7 | ||
|
|
81bf155c38 | ||
|
|
0a0e6c4985 | ||
|
|
7794276536 | ||
|
|
8720e19b91 | ||
|
|
54e28cea23 | ||
|
|
2a25bff836 | ||
|
|
a71a55741f | ||
|
|
bfcb1b9544 | ||
|
|
1a49b4eec3 | ||
|
|
3404d63655 | ||
|
|
8f2d3d7125 | ||
|
|
ad27076c1f | ||
|
|
d7fec62d2e | ||
|
|
3be446880a | ||
|
|
07253b4b49 | ||
|
|
af47c9ae94 | ||
|
|
b1eb8da6a9 | ||
|
|
2852692250 |
14 changed files with 175 additions and 179 deletions
|
|
@ -3,7 +3,7 @@
|
|||
[Flags]
|
||||
public enum FFMpegBinaries : ushort
|
||||
{
|
||||
FFMpeg,
|
||||
FFProbe,
|
||||
FFPlay
|
||||
FFMpeg = 1,
|
||||
FFProbe = 2,
|
||||
FFPlay = 4
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace FFMpegCore.Extensions.Downloader.Enums;
|
|||
public enum FFMpegVersions : ushort
|
||||
{
|
||||
[Description("https://ffbinaries.com/api/v1/version/latest")]
|
||||
Latest,
|
||||
LatestAvailable,
|
||||
|
||||
[Description("https://ffbinaries.com/api/v1/version/6.1")]
|
||||
V6_1,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
/// </summary>
|
||||
public class FFMpegDownloaderException : Exception
|
||||
{
|
||||
public string Detail { get; set; } = "";
|
||||
public readonly string Detail = "";
|
||||
|
||||
public FFMpegDownloaderException(string message) : base(message)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
namespace FFMpegCore.Extensions.Downloader.Extensions;
|
||||
|
||||
internal static class EnumExtensions
|
||||
public static class EnumExtensions
|
||||
{
|
||||
public static string GetDescription(this Enum enumValue)
|
||||
internal static string GetDescription(this Enum enumValue)
|
||||
{
|
||||
var field = enumValue.GetType().GetField(enumValue.ToString());
|
||||
if (field == null)
|
||||
|
|
@ -19,4 +19,13 @@ internal static class EnumExtensions
|
|||
|
||||
return enumValue.ToString();
|
||||
}
|
||||
|
||||
public static TEnum[] GetFlags<TEnum>(this TEnum input) where TEnum : Enum
|
||||
{
|
||||
return Enum.GetValues(input.GetType())
|
||||
.Cast<Enum>()
|
||||
.Where(input.HasFlag)
|
||||
.Cast<TEnum>()
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,5 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<IsPackable>true</IsPackable>
|
||||
<Description>FFMpeg downloader extension for FFMpegCore</Description>
|
||||
|
|
@ -13,7 +8,7 @@
|
|||
<PackageReleaseNotes>
|
||||
</PackageReleaseNotes>
|
||||
<PackageTags>ffmpeg ffprobe convert video audio mediafile resize analyze download</PackageTags>
|
||||
<Authors>Malte Rosenbjerg, Vlad Jerca, Max Bagryantsev, Kerry Cao</Authors>
|
||||
<Authors>Kerry Cao, Malte Rosenbjerg</Authors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,53 +1,83 @@
|
|||
using FFMpegCore.Extensions.Downloader.Enums;
|
||||
using System.IO.Compression;
|
||||
using System.Text.Json;
|
||||
using FFMpegCore.Extensions.Downloader.Enums;
|
||||
using FFMpegCore.Extensions.Downloader.Exceptions;
|
||||
using FFMpegCore.Extensions.Downloader.Services;
|
||||
using FFMpegCore.Extensions.Downloader.Extensions;
|
||||
using FFMpegCore.Extensions.Downloader.Models;
|
||||
|
||||
namespace FFMpegCore.Extensions.Downloader;
|
||||
|
||||
public class FFMpegDownloader
|
||||
public static class FFMpegDownloader
|
||||
{
|
||||
/// <summary>
|
||||
/// Download the latest FFMpeg suite binaries for current platform
|
||||
/// </summary>
|
||||
/// <param name="version">used to explicitly state the version of binary you want to download</param>
|
||||
/// <param name="binaries">used to explicitly state the binaries you want to download (ffmpeg, ffprobe, ffplay)</param>
|
||||
/// <param name="options">used for specifying binary folder to download binaries into. If not provided, GlobalFFOptions are used</param>
|
||||
/// <param name="platformOverride">used to explicitly state the os and architecture you want to download</param>
|
||||
/// <returns>a list of the binaries that have been successfully downloaded</returns>
|
||||
public static async Task<List<string>> DownloadFFMpegSuite(
|
||||
FFMpegVersions version = FFMpegVersions.Latest,
|
||||
public static async Task<List<string>> DownloadBinaries(
|
||||
FFMpegVersions version = FFMpegVersions.LatestAvailable,
|
||||
FFMpegBinaries binaries = FFMpegBinaries.FFMpeg | FFMpegBinaries.FFProbe,
|
||||
FFOptions? options = null,
|
||||
SupportedPlatforms? platformOverride = null)
|
||||
{
|
||||
// get all available versions
|
||||
var versionInfo = await FFbinariesService.GetVersionInfo(version);
|
||||
using var httpClient = new HttpClient();
|
||||
|
||||
// get the download info for the current platform
|
||||
var downloadInfo = versionInfo.BinaryInfo?.GetCompatibleDownloadInfo(platformOverride) ??
|
||||
throw new FFMpegDownloaderException("Failed to get compatible download info");
|
||||
var versionInfo = await httpClient.GetVersionInfo(version);
|
||||
var binariesDictionary = versionInfo.BinaryInfo?.GetCompatibleDownloadInfo(platformOverride) ??
|
||||
throw new FFMpegDownloaderException("Failed to get compatible download info");
|
||||
|
||||
var successList = new List<string>();
|
||||
|
||||
// download ffmpeg if selected
|
||||
if (binaries.HasFlag(FFMpegBinaries.FFMpeg) && downloadInfo.FFMpeg is not null)
|
||||
var relevantOptions = options ?? GlobalFFOptions.Current;
|
||||
if (string.IsNullOrEmpty(relevantOptions.BinaryFolder))
|
||||
{
|
||||
await using var zipStream = await FFbinariesService.DownloadFileAsSteam(new Uri(downloadInfo.FFMpeg));
|
||||
successList.AddRange(FFbinariesService.ExtractZipAndSave(zipStream));
|
||||
throw new FFMpegDownloaderException("Binary folder not specified");
|
||||
}
|
||||
|
||||
// download ffprobe if selected
|
||||
if (binaries.HasFlag(FFMpegBinaries.FFProbe) && downloadInfo.FFProbe is not null)
|
||||
var binaryFlags = binaries.GetFlags();
|
||||
foreach (var binaryFlag in binaryFlags)
|
||||
{
|
||||
await using var zipStream = await FFbinariesService.DownloadFileAsSteam(new Uri(downloadInfo.FFProbe));
|
||||
successList.AddRange(FFbinariesService.ExtractZipAndSave(zipStream));
|
||||
}
|
||||
|
||||
// download ffplay if selected
|
||||
if (binaries.HasFlag(FFMpegBinaries.FFPlay) && downloadInfo.FFPlay is not null)
|
||||
{
|
||||
await using var zipStream = await FFbinariesService.DownloadFileAsSteam(new Uri(downloadInfo.FFPlay));
|
||||
successList.AddRange(FFbinariesService.ExtractZipAndSave(zipStream));
|
||||
if (binariesDictionary.TryGetValue(binaryFlag.ToString().ToLowerInvariant(), out var binaryUrl))
|
||||
{
|
||||
using var zipStream = await httpClient.GetStreamAsync(new Uri(binaryUrl));
|
||||
var extracted = ExtractZipAndSave(zipStream, relevantOptions.BinaryFolder);
|
||||
successList.AddRange(extracted);
|
||||
}
|
||||
}
|
||||
|
||||
return successList;
|
||||
}
|
||||
|
||||
private static async Task<VersionInfo> GetVersionInfo(this HttpClient client, FFMpegVersions version)
|
||||
{
|
||||
var versionUri = version.GetDescription();
|
||||
|
||||
var response = await client.GetAsync(versionUri);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
throw new FFMpegDownloaderException($"Failed to get version info from {versionUri}", "network error");
|
||||
}
|
||||
|
||||
var jsonString = await response.Content.ReadAsStringAsync();
|
||||
var versionInfo = JsonSerializer.Deserialize<VersionInfo>(jsonString);
|
||||
|
||||
return versionInfo ??
|
||||
throw new FFMpegDownloaderException($"Failed to deserialize version info from {versionUri}", jsonString);
|
||||
}
|
||||
|
||||
private static IEnumerable<string> ExtractZipAndSave(Stream zipStream, string binaryFolder)
|
||||
{
|
||||
using var archive = new ZipArchive(zipStream, ZipArchiveMode.Read);
|
||||
foreach (var entry in archive.Entries)
|
||||
{
|
||||
if (entry.Name is "ffmpeg" or "ffmpeg.exe" or "ffprobe.exe" or "ffprobe" or "ffplay.exe" or "ffplay")
|
||||
{
|
||||
var filePath = Path.Combine(binaryFolder, entry.Name);
|
||||
entry.ExtractToFile(filePath, true);
|
||||
yield return filePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,23 +4,23 @@ using FFMpegCore.Extensions.Downloader.Enums;
|
|||
|
||||
namespace FFMpegCore.Extensions.Downloader.Models;
|
||||
|
||||
internal record BinaryInfo
|
||||
internal class BinaryInfo
|
||||
{
|
||||
[JsonPropertyName("windows-64")] public DownloadInfo? Windows64 { get; set; }
|
||||
[JsonPropertyName("windows-64")] public Dictionary<string, string>? Windows64 { get; set; }
|
||||
|
||||
[JsonPropertyName("windows-32")] public DownloadInfo? Windows32 { get; set; }
|
||||
[JsonPropertyName("windows-32")] public Dictionary<string, string>? Windows32 { get; set; }
|
||||
|
||||
[JsonPropertyName("linux-32")] public DownloadInfo? Linux32 { get; set; }
|
||||
[JsonPropertyName("linux-32")] public Dictionary<string, string>? Linux32 { get; set; }
|
||||
|
||||
[JsonPropertyName("linux-64")] public DownloadInfo? Linux64 { get; set; }
|
||||
[JsonPropertyName("linux-64")] public Dictionary<string, string>? Linux64 { get; set; }
|
||||
|
||||
[JsonPropertyName("linux-armhf")] public DownloadInfo? LinuxArmhf { get; set; }
|
||||
[JsonPropertyName("linux-armhf")] public Dictionary<string, string>? LinuxArmhf { get; set; }
|
||||
|
||||
[JsonPropertyName("linux-armel")] public DownloadInfo? LinuxArmel { get; set; }
|
||||
[JsonPropertyName("linux-armel")] public Dictionary<string, string>? LinuxArmel { get; set; }
|
||||
|
||||
[JsonPropertyName("linux-arm64")] public DownloadInfo? LinuxArm64 { get; set; }
|
||||
[JsonPropertyName("linux-arm64")] public Dictionary<string, string>? LinuxArm64 { get; set; }
|
||||
|
||||
[JsonPropertyName("osx-64")] public DownloadInfo? Osx64 { get; set; }
|
||||
[JsonPropertyName("osx-64")] public Dictionary<string, string>? Osx64 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Automatically get the compatible download info for current os and architecture
|
||||
|
|
@ -29,7 +29,7 @@ internal record BinaryInfo
|
|||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||
/// <exception cref="PlatformNotSupportedException"></exception>
|
||||
public DownloadInfo? GetCompatibleDownloadInfo(SupportedPlatforms? platformOverride = null)
|
||||
public Dictionary<string, string>? GetCompatibleDownloadInfo(SupportedPlatforms? platformOverride = null)
|
||||
{
|
||||
if (platformOverride is not null)
|
||||
{
|
||||
|
|
@ -64,7 +64,7 @@ internal record BinaryInfo
|
|||
};
|
||||
}
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && RuntimeInformation.OSArchitecture == Architecture.X64)
|
||||
{
|
||||
return Osx64;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace FFMpegCore.Extensions.Downloader.Models;
|
||||
|
||||
internal record DownloadInfo
|
||||
{
|
||||
[JsonPropertyName("ffmpeg")] public string? FFMpeg { get; set; }
|
||||
|
||||
[JsonPropertyName("ffprobe")] public string? FFProbe { get; set; }
|
||||
|
||||
[JsonPropertyName("ffplay")] public string? FFPlay { get; set; }
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
using System.IO.Compression;
|
||||
using System.Text.Json;
|
||||
using FFMpegCore.Extensions.Downloader.Enums;
|
||||
using FFMpegCore.Extensions.Downloader.Exceptions;
|
||||
using FFMpegCore.Extensions.Downloader.Extensions;
|
||||
using FFMpegCore.Extensions.Downloader.Models;
|
||||
|
||||
namespace FFMpegCore.Extensions.Downloader.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Service to interact with ffbinaries.com API
|
||||
/// </summary>
|
||||
internal class FFbinariesService
|
||||
{
|
||||
/// <summary>
|
||||
/// Get version info from ffbinaries.com
|
||||
/// </summary>
|
||||
/// <param name="version">use to explicitly state the version of ffmpeg you want</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="FFMpegDownloaderException"></exception>
|
||||
internal static async Task<VersionInfo> GetVersionInfo(FFMpegVersions version)
|
||||
{
|
||||
var versionUri = version.GetDescription();
|
||||
|
||||
HttpClient client = new();
|
||||
var response = await client.GetAsync(versionUri);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
throw new FFMpegDownloaderException($"Failed to get version info from {versionUri}", "network error");
|
||||
}
|
||||
|
||||
var jsonString = await response.Content.ReadAsStringAsync();
|
||||
var versionInfo = JsonSerializer.Deserialize<VersionInfo>(jsonString);
|
||||
|
||||
return versionInfo ??
|
||||
throw new FFMpegDownloaderException($"Failed to deserialize version info from {versionUri}", jsonString);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download file from uri
|
||||
/// </summary>
|
||||
/// <param name="address">uri of the file</param>
|
||||
/// <returns></returns>
|
||||
internal static async Task<Stream> DownloadFileAsSteam(Uri address)
|
||||
{
|
||||
var client = new HttpClient();
|
||||
return await client.GetStreamAsync(address);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the binaries from the zip stream and saves them to the current binary folder
|
||||
/// </summary>
|
||||
/// <param name="zipStream">steam of the zip file</param>
|
||||
/// <returns></returns>
|
||||
internal static IEnumerable<string> ExtractZipAndSave(Stream zipStream)
|
||||
{
|
||||
using var archive = new ZipArchive(zipStream, ZipArchiveMode.Read);
|
||||
List<string> files = new();
|
||||
foreach (var entry in archive.Entries)
|
||||
{
|
||||
if (entry.Name is "ffmpeg" or "ffmpeg.exe" or "ffprobe.exe" or "ffprobe" or "ffplay.exe" or "ffplay")
|
||||
{
|
||||
entry.ExtractToFile(Path.Combine(GlobalFFOptions.Current.BinaryFolder, entry.Name), true);
|
||||
files.Add(Path.Combine(GlobalFFOptions.Current.BinaryFolder, entry.Name));
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +1,53 @@
|
|||
using FFMpegCore.Extensions.Downloader;
|
||||
using FFMpegCore.Extensions.Downloader.Enums;
|
||||
using FFMpegCore.Test.Utilities;
|
||||
|
||||
namespace FFMpegCore.Test;
|
||||
|
||||
[TestClass]
|
||||
public class DownloaderTests
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task GetSpecificVersionTest()
|
||||
private FFOptions _ffOptions;
|
||||
|
||||
[TestInitialize]
|
||||
public void InitializeTestFolder()
|
||||
{
|
||||
var binaries = await FFMpegDownloader.DownloadFFMpegSuite(FFMpegVersions.V6_1);
|
||||
Assert.HasCount(2, binaries);
|
||||
var tempDownloadFolder = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempDownloadFolder);
|
||||
_ffOptions = new FFOptions { BinaryFolder = tempDownloadFolder };
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCleanup]
|
||||
public void DeleteTestFolder()
|
||||
{
|
||||
Directory.Delete(_ffOptions.BinaryFolder, true);
|
||||
}
|
||||
|
||||
[OsSpecificTestMethod(OsPlatforms.Windows | OsPlatforms.Linux)]
|
||||
public async Task GetSpecificVersionTest()
|
||||
{
|
||||
var binaries = await FFMpegDownloader.DownloadBinaries(FFMpegVersions.V6_1, options: _ffOptions);
|
||||
try
|
||||
{
|
||||
Assert.HasCount(2, binaries);
|
||||
}
|
||||
finally
|
||||
{
|
||||
binaries.ForEach(File.Delete);
|
||||
}
|
||||
}
|
||||
|
||||
[OsSpecificTestMethod(OsPlatforms.Windows | OsPlatforms.Linux)]
|
||||
public async Task GetAllLatestSuiteTest()
|
||||
{
|
||||
var binaries = await FFMpegDownloader.DownloadFFMpegSuite();
|
||||
Assert.HasCount(2, binaries);
|
||||
var binaries = await FFMpegDownloader.DownloadBinaries(options: _ffOptions);
|
||||
try
|
||||
{
|
||||
Assert.HasCount(2, binaries);
|
||||
}
|
||||
finally
|
||||
{
|
||||
binaries.ForEach(File.Delete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
42
FFMpegCore.Test/Utilities/OsSpecificTestMethod.cs
Normal file
42
FFMpegCore.Test/Utilities/OsSpecificTestMethod.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using FFMpegCore.Extensions.Downloader.Extensions;
|
||||
|
||||
namespace FFMpegCore.Test.Utilities;
|
||||
|
||||
[Flags]
|
||||
internal enum OsPlatforms : ushort
|
||||
{
|
||||
Windows = 1,
|
||||
Linux = 2,
|
||||
MacOS = 4
|
||||
}
|
||||
|
||||
internal class OsSpecificTestMethod : TestMethodAttribute
|
||||
{
|
||||
private readonly IEnumerable<OSPlatform> _supportedOsPlatforms;
|
||||
|
||||
public OsSpecificTestMethod(OsPlatforms supportedOsPlatforms, [CallerFilePath] string callerFilePath = "",
|
||||
[CallerLineNumber] int callerLineNumber = -1) : base(callerFilePath, callerLineNumber)
|
||||
{
|
||||
_supportedOsPlatforms = supportedOsPlatforms.GetFlags()
|
||||
.Select(flag => OSPlatform.Create(flag.ToString().ToUpperInvariant()))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public override async Task<TestResult[]> ExecuteAsync(ITestMethod testMethod)
|
||||
{
|
||||
if (_supportedOsPlatforms.Any(RuntimeInformation.IsOSPlatform))
|
||||
{
|
||||
return await base.ExecuteAsync(testMethod);
|
||||
}
|
||||
|
||||
var message = $"Test only executed on specific platforms: {string.Join(", ", _supportedOsPlatforms.Select(platform => platform.ToString()))}";
|
||||
{
|
||||
return
|
||||
[
|
||||
new TestResult { Outcome = UnitTestOutcome.Inconclusive, TestFailureException = new AssertInconclusiveException(message) }
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace FFMpegCore.Test.Utilities;
|
||||
|
||||
public class WindowsOnlyTestMethod : TestMethodAttribute
|
||||
{
|
||||
public WindowsOnlyTestMethod([CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = -1)
|
||||
: base(callerFilePath, callerLineNumber)
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<TestResult[]> ExecuteAsync(ITestMethod testMethod)
|
||||
{
|
||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
var message = "Test not executed on other platforms than Windows";
|
||||
{
|
||||
return
|
||||
[
|
||||
new TestResult { Outcome = UnitTestOutcome.Inconclusive, TestFailureException = new AssertInconclusiveException(message) }
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return await base.ExecuteAsync(testMethod);
|
||||
}
|
||||
}
|
||||
|
|
@ -93,7 +93,7 @@ public class VideoTest
|
|||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[WindowsOnlyTestMethod]
|
||||
[OsSpecificTestMethod(OsPlatforms.Windows)]
|
||||
[Timeout(BaseTimeoutMilliseconds, CooperativeCancellation = true)]
|
||||
[DataRow(PixelFormat.Format24bppRgb)]
|
||||
[DataRow(PixelFormat.Format32bppArgb)]
|
||||
|
|
@ -125,7 +125,7 @@ public class VideoTest
|
|||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[WindowsOnlyTestMethod]
|
||||
[OsSpecificTestMethod(OsPlatforms.Windows)]
|
||||
[Timeout(BaseTimeoutMilliseconds, CooperativeCancellation = true)]
|
||||
public void Video_ToMP4_Args_Pipe_DifferentImageSizes_WindowsOnly()
|
||||
{
|
||||
|
|
@ -157,7 +157,7 @@ public class VideoTest
|
|||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[WindowsOnlyTestMethod]
|
||||
[OsSpecificTestMethod(OsPlatforms.Windows)]
|
||||
[Timeout(BaseTimeoutMilliseconds, CooperativeCancellation = true)]
|
||||
public async Task Video_ToMP4_Args_Pipe_DifferentImageSizes_WindowsOnly_Async()
|
||||
{
|
||||
|
|
@ -189,7 +189,7 @@ public class VideoTest
|
|||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[WindowsOnlyTestMethod]
|
||||
[OsSpecificTestMethod(OsPlatforms.Windows)]
|
||||
[Timeout(BaseTimeoutMilliseconds, CooperativeCancellation = true)]
|
||||
public void Video_ToMP4_Args_Pipe_DifferentPixelFormats_WindowsOnly()
|
||||
{
|
||||
|
|
@ -222,7 +222,7 @@ public class VideoTest
|
|||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[WindowsOnlyTestMethod]
|
||||
[OsSpecificTestMethod(OsPlatforms.Windows)]
|
||||
[Timeout(BaseTimeoutMilliseconds, CooperativeCancellation = true)]
|
||||
public async Task Video_ToMP4_Args_Pipe_DifferentPixelFormats_WindowsOnly_Async()
|
||||
{
|
||||
|
|
@ -397,7 +397,7 @@ public class VideoTest
|
|||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[WindowsOnlyTestMethod]
|
||||
[OsSpecificTestMethod(OsPlatforms.Windows)]
|
||||
[Timeout(BaseTimeoutMilliseconds, CooperativeCancellation = true)]
|
||||
[DataRow(PixelFormat.Format24bppRgb)]
|
||||
[DataRow(PixelFormat.Format32bppArgb)]
|
||||
|
|
@ -446,7 +446,7 @@ public class VideoTest
|
|||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[WindowsOnlyTestMethod]
|
||||
[OsSpecificTestMethod(OsPlatforms.Windows)]
|
||||
[Timeout(BaseTimeoutMilliseconds, CooperativeCancellation = true)]
|
||||
[DataRow(SKColorType.Rgb565)]
|
||||
[DataRow(SKColorType.Bgra8888)]
|
||||
|
|
@ -483,7 +483,7 @@ public class VideoTest
|
|||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[WindowsOnlyTestMethod]
|
||||
[OsSpecificTestMethod(OsPlatforms.Windows)]
|
||||
[Timeout(BaseTimeoutMilliseconds, CooperativeCancellation = true)]
|
||||
[DataRow(PixelFormat.Format24bppRgb)]
|
||||
[DataRow(PixelFormat.Format32bppArgb)]
|
||||
|
|
@ -516,7 +516,7 @@ public class VideoTest
|
|||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[WindowsOnlyTestMethod]
|
||||
[OsSpecificTestMethod(OsPlatforms.Windows)]
|
||||
[Timeout(BaseTimeoutMilliseconds, CooperativeCancellation = true)]
|
||||
public void Video_Snapshot_InMemory_SystemDrawingCommon()
|
||||
{
|
||||
|
|
@ -840,7 +840,7 @@ public class VideoTest
|
|||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[WindowsOnlyTestMethod]
|
||||
[OsSpecificTestMethod(OsPlatforms.Windows)]
|
||||
[Timeout(BaseTimeoutMilliseconds, CooperativeCancellation = true)]
|
||||
public void Video_TranscodeInMemory_WindowsOnly()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ If you want to use `System.Drawing.Bitmap`s as `IVideoFrame`s, a `BitmapVideoFra
|
|||
## Runtime Auto Installation
|
||||
You can install a version of ffmpeg suite at runtime using `FFMpegDownloader.DownloadFFMpegSuite();`
|
||||
|
||||
This feature uses the api from [ffbinaries](https://ffbinaries.com/api).
|
||||
This feature uses the api from [ffbinaries](https://ffbinaries.com/api).
|
||||
|
||||
## Manual Installation
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue