Files
flowframes/Code/MiscUtils/OutputUtils.cs

287 lines
11 KiB
C#

using Flowframes.Data;
using Flowframes.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using static Flowframes.Data.Enums.Encoding;
using Encoder = Flowframes.Data.Enums.Encoding.Encoder;
using PixFmt = Flowframes.Data.Enums.Encoding.PixelFormat;
namespace Flowframes.MiscUtils
{
internal class OutputUtils
{
public static EncoderInfoVideo GetEncoderInfoVideo(Encoder encoder)
{
if (encoder == Encoder.X264)
{
return new EncoderInfoVideo
{
Codec = Codec.H264,
Name = "libx264",
PixelFormats = new List<PixFmt>() { PixFmt.Yuv420P, PixFmt.Yuv444P },
QualityLevels = ParseUtils.GetEnumStrings<Quality.Common>(),
QualityDefault = (int)Quality.Common.VeryHigh,
};
}
if (encoder == Encoder.X265)
{
return new EncoderInfoVideo
{
Codec = Codec.H265,
Name = "libx265",
PixelFormats = new List<PixFmt>() { PixFmt.Yuv420P, PixFmt.Yuv444P, PixFmt.Yuv420P10Le, PixFmt.Yuv444P10Le },
QualityLevels = ParseUtils.GetEnumStrings<Quality.Common>(),
QualityDefault = (int)Quality.Common.VeryHigh,
};
}
if (encoder == Encoder.Nvenc264)
{
return new EncoderInfoVideo
{
Codec = Codec.H264,
Name = "h264_nvenc",
PixelFormats = new List<PixFmt>() { PixFmt.Yuv420P, PixFmt.Yuv444P },
QualityLevels = ParseUtils.GetEnumStrings<Quality.Common>(),
QualityDefault = (int)Quality.Common.VeryHigh,
HwAccelerated = true,
};
}
if (encoder == Encoder.SvtAv1)
{
return new EncoderInfoVideo
{
Codec = Codec.AV1,
Name = "libsvtav1",
PixelFormats = new List<PixFmt>() { PixFmt.Yuv420P, PixFmt.Yuv420P10Le },
PixelFormatDefault = PixFmt.Yuv420P10Le,
QualityLevels = ParseUtils.GetEnumStrings<Quality.Common>(),
QualityDefault = (int)Quality.Common.VeryHigh,
MaxFramerate = 240,
};
}
if (encoder == Encoder.VpxVp9)
{
return new EncoderInfoVideo
{
Codec = Codec.VP9,
Name = "libvpx-vp9",
PixelFormats = new List<PixFmt>() { PixFmt.Yuv420P, PixFmt.Yuv444P, PixFmt.Yuv420P10Le, PixFmt.Yuv444P, PixFmt.Yuv444P10Le },
QualityLevels = ParseUtils.GetEnumStrings<Quality.Common>(),
QualityDefault = (int)Quality.Common.VeryHigh,
};
}
if (encoder == Encoder.Nvenc265)
{
return new EncoderInfoVideo
{
Codec = Codec.H265,
Name = "hevc_nvenc",
PixelFormats = new List<PixFmt>() { PixFmt.Yuv420P, PixFmt.Yuv444P, PixFmt.Yuv420P10Le },
QualityLevels = ParseUtils.GetEnumStrings<Quality.Common>(),
QualityDefault = (int)Quality.Common.VeryHigh,
HwAccelerated = true,
};
}
if (encoder == Encoder.NvencAv1)
{
return new EncoderInfoVideo
{
Codec = Codec.AV1,
Name = "av1_nvenc",
PixelFormats = new List<PixFmt>() { PixFmt.Yuv420P, PixFmt.Yuv444P, PixFmt.Yuv420P10Le },
QualityLevels = ParseUtils.GetEnumStrings<Quality.Common>(),
QualityDefault = (int)Quality.Common.VeryHigh,
PixelFormatDefault = PixFmt.Yuv420P10Le,
HwAccelerated = true,
};
}
if (encoder == Encoder.ProResKs)
{
return new EncoderInfoVideo
{
Codec = Codec.ProRes,
Name = "prores_ks",
PixelFormats = new List<PixFmt>() { PixFmt.Yuv422P10Le, PixFmt.Yuv444P10Le, PixFmt.Yuva444P10Le },
QualityLevels = ParseUtils.GetEnumStrings<Quality.ProResProfile>(),
QualityDefault = (int)Quality.ProResProfile.Hq,
};
}
if (encoder == Encoder.Gif)
{
return new EncoderInfoVideo
{
Codec = Codec.Gif,
Name = "gif",
PixelFormats = new List<PixFmt>() { PixFmt.Rgb8 },
QualityLevels = ParseUtils.GetEnumStrings<Quality.GifColors>(),
QualityDefault = (int)Quality.GifColors.High128,
OverideExtension = "gif",
MaxFramerate = 50,
};
}
if (encoder == Encoder.Ffv1)
{
return new EncoderInfoVideo
{
Codec = Codec.Ffv1,
Name = "ffv1",
PixelFormats = new List<PixFmt>() { PixFmt.Yuv420P, PixFmt.Yuv444P, PixFmt.Yuv422P, PixFmt.Yuv422P, PixFmt.Yuv420P10Le, PixFmt.Yuv444P10Le },
Lossless = true,
};
}
if (encoder == Encoder.Huffyuv)
{
return new EncoderInfoVideo
{
Codec = Codec.Huffyuv,
Name = "huffyuv",
PixelFormats = new List<PixFmt>() { PixFmt.Yuv422P, PixFmt.Rgb24 },
Lossless = true,
};
}
if (encoder == Encoder.Magicyuv)
{
return new EncoderInfoVideo
{
Codec = Codec.Magicyuv,
Name = "magicyuv",
PixelFormats = new List<PixFmt>() { PixFmt.Yuv420P, PixFmt.Yuv422P, PixFmt.Yuv444P },
Lossless = true,
};
}
if (encoder == Encoder.Rawvideo)
{
return new EncoderInfoVideo
{
Codec = Codec.Rawvideo,
Name = "rawvideo",
Lossless = true,
};
}
if (encoder == Encoder.Png)
{
return new EncoderInfoVideo
{
Codec = Codec.Png,
Name = "png",
PixelFormats = new List<PixFmt>() { PixFmt.Rgb24, PixFmt.Rgba },
Lossless = true,
IsImageSequence = true,
OverideExtension = "png",
};
}
if (encoder == Encoder.Jpeg)
{
return new EncoderInfoVideo
{
Codec = Codec.Jpeg,
Name = "mjpeg",
PixelFormats = new List<PixFmt>() { PixFmt.Yuv420P, PixFmt.Yuv422P, PixFmt.Yuv444P },
IsImageSequence = true,
OverideExtension = "jpg",
};
}
if (encoder == Encoder.Webp)
{
return new EncoderInfoVideo
{
Codec = Codec.Webp,
Name = "libwebp",
PixelFormats = new List<PixFmt>() { PixFmt.Yuv420P, PixFmt.Yuva420P },
IsImageSequence = true,
OverideExtension = "webp",
};
}
return new EncoderInfoVideo();
}
public static List<Codec> GetSupportedCodecs(Enums.Output.Format format)
{
switch (format)
{
case Enums.Output.Format.Mp4: return new List<Codec> { Codec.H264, Codec.H265, Codec.AV1 };
case Enums.Output.Format.Mkv: return new List<Codec> { Codec.H264, Codec.H265, Codec.AV1, Codec.VP9 };
case Enums.Output.Format.Webm: return new List<Codec> { Codec.VP9, Codec.AV1 };
case Enums.Output.Format.Mov: return new List<Codec> { Codec.ProRes };
case Enums.Output.Format.Avi: return new List<Codec> { Codec.Ffv1, Codec.Huffyuv, Codec.Magicyuv, Codec.Rawvideo };
case Enums.Output.Format.Gif: return new List<Codec> { Codec.Gif };
case Enums.Output.Format.Images: return new List<Codec> { Codec.Png, Codec.Jpeg, Codec.Webp };
case Enums.Output.Format.Realtime: return new List<Codec> { };
default: return new List<Codec> { };
}
}
public static List<Encoder> GetAvailableEncoders(Enums.Output.Format format)
{
var allEncoders = Enum.GetValues(typeof(Encoder)).Cast<Encoder>();
var supportedCodecs = GetSupportedCodecs(format);
var availableEncoders = supportedCodecs.SelectMany(codec => allEncoders.Where(enc => enc.GetInfo().Codec == codec));
return availableEncoders.ToList();
}
public static int GetCrf (Quality.Common qualityLevel, Encoder encoder)
{
int baseCrf = Crfs[qualityLevel];
float multiplier = 1f;
if (encoder == Encoder.X265)
multiplier = 1.0f;
if (encoder == Encoder.VpxVp9)
multiplier = 1.3f;
if (encoder == Encoder.SvtAv1)
multiplier = 1.3f;
if (encoder == Encoder.Nvenc264)
multiplier = 1.1f;
if (encoder == Encoder.Nvenc265)
multiplier = 1.15f;
if (encoder == Encoder.NvencAv1)
multiplier = 1.3f;
return (baseCrf * multiplier).RoundToInt();
}
public static int GetGifColors (Quality.GifColors qualityLevel)
{
switch (qualityLevel)
{
case Quality.GifColors.Max256: return 256;
case Quality.GifColors.High128: return 128;
case Quality.GifColors.Medium64: return 64;
case Quality.GifColors.Low32: return 32;
case Quality.GifColors.VeryLow16: return 16;
default: return 128;
}
}
public static Dictionary<Quality.Common, int> Crfs = new Dictionary<Quality.Common, int>
{
{ Quality.Common.Lossless, 0 },
{ Quality.Common.VeryHigh, 16 },
{ Quality.Common.High, 20 },
{ Quality.Common.Medium, 26 },
{ Quality.Common.Low, 32 },
{ Quality.Common.VeryLow, 40 },
};
}
}