Add TIFF output, additional pix fmts for some encoders

This commit is contained in:
N00MKRAD
2024-01-09 15:49:47 +01:00
parent b6293a1940
commit 74f107492a
7 changed files with 82 additions and 50 deletions

View File

@@ -1,20 +1,14 @@
using System; namespace Flowframes.Data
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Flowframes.Data
{ {
public class EncoderInfo public class EncoderInfo
{ {
public string Name { get; set; } = "unknown"; public virtual string FfmpegName { get; set; } = "";
public EncoderInfo() { } public EncoderInfo() { }
public EncoderInfo(string name) public EncoderInfo(string name)
{ {
Name = name; FfmpegName = name;
} }
} }
} }

View File

@@ -1,8 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Flowframes.Data.Enums.Encoding; using static Flowframes.Data.Enums.Encoding;
namespace Flowframes.Data namespace Flowframes.Data
@@ -20,5 +16,16 @@ namespace Flowframes.Data
public string OverideExtension { get; set; } = ""; public string OverideExtension { get; set; } = "";
public List<string> QualityLevels { get; set; } = new List<string> (); public List<string> QualityLevels { get; set; } = new List<string> ();
public int QualityDefault { get; set; } = 0; public int QualityDefault { get; set; } = 0;
public string Name
{
get
{
return FfmpegName.IsEmpty() ? Codec.ToString().Lower() : FfmpegName;
}
set
{
FfmpegName = value;
}
}
} }
} }

View File

@@ -5,15 +5,19 @@
public class Output public class Output
{ {
public enum Format { Mp4, Mkv, Webm, Mov, Avi, Gif, Images, Realtime }; public enum Format { Mp4, Mkv, Webm, Mov, Avi, Gif, Images, Realtime };
public enum ImageFormat { Png, Jpeg, Webp }; public enum ImageFormat { Png, Jpeg, Webp, Tiff };
public enum Dithering { None, Bayer, FloydSteinberg }; public enum Dithering { None, Bayer, FloydSteinberg };
} }
public class Encoding public class Encoding
{ {
public enum Codec { H264, H265, AV1, VP9, ProRes, Gif, Png, Jpeg, Webp, Ffv1, Huffyuv, Magicyuv, Rawvideo } public enum Codec { H264, H265, AV1, VP9, ProRes, Gif, Png, Jpeg, Webp, Tiff, Ffv1, Huffyuv, Magicyuv, Rawvideo }
public enum Encoder { X264, X265, SvtAv1, VpxVp9, Nvenc264, Nvenc265, NvencAv1, Amf264, Amf265, Qsv264, Qsv265, ProResKs, Gif, Png, Jpeg, Webp, Ffv1, Huffyuv, Magicyuv, Rawvideo } public enum Encoder { X264, X265, SvtAv1, VpxVp9, Nvenc264, Nvenc265, NvencAv1, Amf264, Amf265, Qsv264, Qsv265, ProResKs, Gif, Png, Jpeg, Webp, Tiff, Ffv1, Huffyuv, Magicyuv, Rawvideo }
public enum PixelFormat { Yuv420P, Yuva420P, Yuv420P10Le, Yuv422P, Yuv422P10Le, Yuv444P, Yuv444P10Le, Yuva444P10Le, Rgb24, Rgba, Pal8 }; public enum PixelFormat
{
Yuv420P, Yuva420P, Yuv420P10Le, Yuv422P, Yuv422P10Le, Yuv444P, Yuv444P10Le, Yuva444P10Le, Yuv444P12Le, Yuv444P16Le, P010Le, P016Le, // YUV & similar
Rgb24, Rgba, Rgb48Le, Rgb48Be, Rgba64Le, Rgba64Be, Pal8 // RGB & other
};
public class Quality public class Quality
{ {

View File

@@ -34,6 +34,7 @@ namespace Flowframes.Data
{ Enums.Encoding.Encoder.Png.ToString(), "PNG" }, { Enums.Encoding.Encoder.Png.ToString(), "PNG" },
{ Enums.Encoding.Encoder.Jpeg.ToString(), "JPEG" }, { Enums.Encoding.Encoder.Jpeg.ToString(), "JPEG" },
{ Enums.Encoding.Encoder.Webp.ToString(), "WEBP" }, { Enums.Encoding.Encoder.Webp.ToString(), "WEBP" },
{ Enums.Encoding.Encoder.Tiff.ToString(), "TIFF" },
{ Enums.Encoding.Encoder.Ffv1.ToString(), "FFV1" }, { Enums.Encoding.Encoder.Ffv1.ToString(), "FFV1" },
{ Enums.Encoding.Encoder.Huffyuv.ToString(), "HuffYUV" }, { Enums.Encoding.Encoder.Huffyuv.ToString(), "HuffYUV" },
{ Enums.Encoding.Encoder.Magicyuv.ToString(), "MagicYUV" }, { Enums.Encoding.Encoder.Magicyuv.ToString(), "MagicYUV" },
@@ -50,9 +51,15 @@ namespace Flowframes.Data
{ Enums.Encoding.PixelFormat.Yuv444P.ToString(), "YUV 4:4:4 8-bit" }, { Enums.Encoding.PixelFormat.Yuv444P.ToString(), "YUV 4:4:4 8-bit" },
{ Enums.Encoding.PixelFormat.Yuv444P10Le.ToString(), "YUV 4:4:4 10-bit" }, { Enums.Encoding.PixelFormat.Yuv444P10Le.ToString(), "YUV 4:4:4 10-bit" },
{ Enums.Encoding.PixelFormat.Yuva444P10Le.ToString(), "YUVA 4:4:4 10-bit" }, { Enums.Encoding.PixelFormat.Yuva444P10Le.ToString(), "YUVA 4:4:4 10-bit" },
{ Enums.Encoding.PixelFormat.Yuv444P12Le.ToString(), "YUV 4:4:4 12-bit" },
{ Enums.Encoding.PixelFormat.Yuv444P16Le.ToString(), "YUV 4:4:4 16-bit" },
{ Enums.Encoding.PixelFormat.Rgb24.ToString(), "RGB 8-bit" }, { Enums.Encoding.PixelFormat.Rgb24.ToString(), "RGB 8-bit" },
{ Enums.Encoding.PixelFormat.Pal8.ToString(), "256-color Palette" },
{ Enums.Encoding.PixelFormat.Rgba.ToString(), "RGBA 8-bit" }, { Enums.Encoding.PixelFormat.Rgba.ToString(), "RGBA 8-bit" },
{ Enums.Encoding.PixelFormat.Rgb48Le.ToString(), "RGB 12-bit LE" },
{ Enums.Encoding.PixelFormat.Rgb48Be.ToString(), "RGB 12-bit BE" },
{ Enums.Encoding.PixelFormat.Rgba64Le.ToString(), "RGBA 16-bit LE" },
{ Enums.Encoding.PixelFormat.Rgba64Be.ToString(), "RGBA 16-bit BE" },
{ Enums.Encoding.PixelFormat.Pal8.ToString(), "256-color Palette" },
}; };
public static Dictionary<string, string> VideoQuality = new Dictionary<string, string> public static Dictionary<string, string> VideoQuality = new Dictionary<string, string>

View File

@@ -87,6 +87,13 @@ namespace Flowframes.Forms.Main
{ {
comboxOutputFormat.FillFromEnum<Enums.Output.Format>(Strings.OutputFormat, 0); comboxOutputFormat.FillFromEnum<Enums.Output.Format>(Strings.OutputFormat, 0);
UpdateOutputUi(); UpdateOutputUi();
if (Debugger.IsAttached)
{
Logger.Log($"Formats: {string.Join(", ", Enum.GetValues(typeof(Enums.Output.Format)).Cast<Enums.Output.Format>().Select(e => Strings.OutputFormat.Get(e.ToString())))}", true);
Logger.Log($"Encoders: {string.Join(", ", Enum.GetValues(typeof(Enums.Encoding.Encoder)).Cast<Enums.Encoding.Encoder>().Select(e => Strings.Encoder.Get(e.ToString())))}", true);
Logger.Log($"Pixel Formats: {string.Join(", ", Enum.GetValues(typeof(Enums.Encoding.PixelFormat)).Cast<Enums.Encoding.PixelFormat>().Select(e => Strings.PixelFormat.Get(e.ToString())))}", true);
}
} }
public async void ResetOutputUi() public async void ResetOutputUi()

View File

@@ -238,7 +238,7 @@ namespace Flowframes.Media
PixelFormat pixFmt = settings.PixelFormat; PixelFormat pixFmt = settings.PixelFormat;
if (settings.Format == Enums.Output.Format.Realtime) if (settings.Format == Enums.Output.Format.Realtime)
pixFmt = PixelFormat.Yuv444P; pixFmt = PixelFormat.Yuv444P16Le;
if (pixFmt == (PixelFormat)(-1)) // No pixel format set in GUI if (pixFmt == (PixelFormat)(-1)) // No pixel format set in GUI
pixFmt = info.PixelFormatDefault != (PixelFormat)(-1) ? info.PixelFormatDefault : info.PixelFormats.First(); // Set default or fallback to first in list pixFmt = info.PixelFormatDefault != (PixelFormat)(-1) ? info.PixelFormatDefault : info.PixelFormats.First(); // Set default or fallback to first in list
@@ -248,9 +248,6 @@ namespace Flowframes.Media
if (enc == Encoder.X264 || enc == Encoder.X265 || enc == Encoder.SvtAv1 || enc == Encoder.VpxVp9 || enc == Encoder.Nvenc264 || enc == Encoder.Nvenc265 || enc == Encoder.NvencAv1) if (enc == Encoder.X264 || enc == Encoder.X265 || enc == Encoder.SvtAv1 || enc == Encoder.VpxVp9 || enc == Encoder.Nvenc264 || enc == Encoder.Nvenc265 || enc == Encoder.NvencAv1)
args.Add(GetKeyIntArg(fps, keyint)); args.Add(GetKeyIntArg(fps, keyint));
if (pixFmt != (PixelFormat)(-1))
args.Add($"-pix_fmt {pixFmt.ToString().Lower()}");
if (enc == Encoder.X264) if (enc == Encoder.X264)
{ {
string preset = Config.Get(Config.Key.ffEncPreset).ToLowerInvariant().Remove(" "); // TODO: Replace this ugly stuff with enums string preset = Config.Get(Config.Key.ffEncPreset).ToLowerInvariant().Remove(" "); // TODO: Replace this ugly stuff with enums
@@ -290,22 +287,28 @@ namespace Flowframes.Media
} }
} }
// Fix NVENC pixel formats
if (enc.ToString().StartsWith("Nvenc"))
{
if (pixFmt == PixelFormat.Yuv420P10Le) pixFmt = PixelFormat.P010Le;
}
if (enc == Encoder.Nvenc264) if (enc == Encoder.Nvenc264)
{ {
int crf = GetCrf(settings); int crf = GetCrf(settings);
args.Add($"-b:v 0 {(crf > 0 ? $"-cq {crf} -preset p7" : "-preset lossless")}"); args.Add($"-b:v 0 -preset p7 {(crf > 0 ? $"-cq {crf}" : "-tune lossless")}");
} }
if (enc == Encoder.Nvenc265) if (enc == Encoder.Nvenc265)
{ {
int crf = GetCrf(settings); int crf = GetCrf(settings);
args.Add($"-b:v 0 {(crf > 0 ? $"-cq {crf} -preset p7" : "-preset lossless")}"); args.Add($"-b:v 0 -preset p7 {(crf > 0 ? $"-cq {crf}" : "-tune lossless")}");
} }
if (enc == Encoder.NvencAv1) if (enc == Encoder.NvencAv1)
{ {
int crf = GetCrf(settings); int crf = GetCrf(settings);
args.Add($"-b:v 0 -preset p7 {(crf > 0 ? $"-cq {crf}" : "-tune lossless")}"); args.Add($"-b:v 0 -preset p7 -cq {crf}");
} }
if (enc == Encoder.Amf264) if (enc == Encoder.Amf264)
@@ -355,6 +358,9 @@ namespace Flowframes.Media
args.Add($"-q:v {OutputUtils.WebpQuality[qualityLevel]}"); args.Add($"-q:v {OutputUtils.WebpQuality[qualityLevel]}");
} }
if (pixFmt != (PixelFormat)(-1))
args.Add($"-pix_fmt {pixFmt.ToString().Lower()}");
return new string[] { string.Join(" ", args) }; return new string[] { string.Join(" ", args) };
} }

View File

@@ -39,19 +39,6 @@ namespace Flowframes.MiscUtils
}; };
} }
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) if (encoder == Encoder.SvtAv1)
{ {
return new EncoderInfoVideo return new EncoderInfoVideo
@@ -79,6 +66,19 @@ namespace Flowframes.MiscUtils
}; };
} }
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.Nvenc265) if (encoder == Encoder.Nvenc265)
{ {
return new EncoderInfoVideo return new EncoderInfoVideo
@@ -181,7 +181,6 @@ namespace Flowframes.MiscUtils
return new EncoderInfoVideo return new EncoderInfoVideo
{ {
Codec = Codec.Gif, Codec = Codec.Gif,
Name = "gif",
PixelFormats = new List<PixFmt>() { PixFmt.Pal8 }, PixelFormats = new List<PixFmt>() { PixFmt.Pal8 },
PixelFormatDefault = PixFmt.Pal8, PixelFormatDefault = PixFmt.Pal8,
QualityLevels = ParseUtils.GetEnumStrings<Quality.GifColors>(), QualityLevels = ParseUtils.GetEnumStrings<Quality.GifColors>(),
@@ -197,8 +196,7 @@ namespace Flowframes.MiscUtils
return new EncoderInfoVideo return new EncoderInfoVideo
{ {
Codec = Codec.Ffv1, Codec = Codec.Ffv1,
Name = "ffv1", PixelFormats = new List<PixFmt>() { PixFmt.Yuv420P, PixFmt.Yuv444P, PixFmt.Yuv422P, PixFmt.Yuv422P, PixFmt.Yuv420P10Le, PixFmt.Yuv444P10Le, PixFmt.Yuv444P12Le, PixFmt.Yuv444P16Le, PixFmt.Rgb48Le, PixFmt.Rgba64Le },
PixelFormats = new List<PixFmt>() { PixFmt.Yuv420P, PixFmt.Yuv444P, PixFmt.Yuv422P, PixFmt.Yuv422P, PixFmt.Yuv420P10Le, PixFmt.Yuv444P10Le },
Lossless = true, Lossless = true,
}; };
} }
@@ -208,8 +206,7 @@ namespace Flowframes.MiscUtils
return new EncoderInfoVideo return new EncoderInfoVideo
{ {
Codec = Codec.Huffyuv, Codec = Codec.Huffyuv,
Name = "huffyuv", PixelFormats = new List<PixFmt>() { PixFmt.Yuv422P, PixFmt.Rgb24, PixFmt.Rgba },
PixelFormats = new List<PixFmt>() { PixFmt.Yuv422P, PixFmt.Rgb24 },
Lossless = true, Lossless = true,
}; };
} }
@@ -219,7 +216,6 @@ namespace Flowframes.MiscUtils
return new EncoderInfoVideo return new EncoderInfoVideo
{ {
Codec = Codec.Magicyuv, Codec = Codec.Magicyuv,
Name = "magicyuv",
PixelFormats = new List<PixFmt>() { PixFmt.Yuv420P, PixFmt.Yuv422P, PixFmt.Yuv444P }, PixelFormats = new List<PixFmt>() { PixFmt.Yuv420P, PixFmt.Yuv422P, PixFmt.Yuv444P },
Lossless = true, Lossless = true,
}; };
@@ -230,7 +226,6 @@ namespace Flowframes.MiscUtils
return new EncoderInfoVideo return new EncoderInfoVideo
{ {
Codec = Codec.Rawvideo, Codec = Codec.Rawvideo,
Name = "rawvideo",
Lossless = true, Lossless = true,
}; };
} }
@@ -240,8 +235,7 @@ namespace Flowframes.MiscUtils
return new EncoderInfoVideo return new EncoderInfoVideo
{ {
Codec = Codec.Png, Codec = Codec.Png,
Name = "png", PixelFormats = new List<PixFmt>() { PixFmt.Rgb24, PixFmt.Rgba, PixFmt.Rgb48Be, PixFmt.Rgba64Be },
PixelFormats = new List<PixFmt>() { PixFmt.Rgb24, PixFmt.Rgba },
PixelFormatDefault = PixFmt.Rgb24, PixelFormatDefault = PixFmt.Rgb24,
Lossless = true, Lossless = true,
IsImageSequence = true, IsImageSequence = true,
@@ -269,7 +263,7 @@ namespace Flowframes.MiscUtils
{ {
Codec = Codec.Webp, Codec = Codec.Webp,
Name = "libwebp", Name = "libwebp",
PixelFormats = new List<PixFmt>() { PixFmt.Yuv420P, PixFmt.Yuva420P }, PixelFormats = new List<PixFmt>() { PixFmt.Yuv420P, PixFmt.Yuva420P, PixFmt.Rgba }, // Actually only supports BGRA not RGBA, but ffmpeg will auto-pick that
QualityLevels = ParseUtils.GetEnumStrings<Quality.JpegWebm>(), QualityLevels = ParseUtils.GetEnumStrings<Quality.JpegWebm>(),
QualityDefault = (int)Quality.JpegWebm.ImgHigh, QualityDefault = (int)Quality.JpegWebm.ImgHigh,
IsImageSequence = true, IsImageSequence = true,
@@ -277,6 +271,19 @@ namespace Flowframes.MiscUtils
}; };
} }
if (encoder == Encoder.Tiff)
{
return new EncoderInfoVideo
{
Codec = Codec.Tiff,
PixelFormats = new List<PixFmt>() { PixFmt.Yuv420P, PixFmt.Yuv422P, PixFmt.Yuv444P, PixFmt.Yuv444P16Le, PixFmt.Rgb24, PixFmt.Rgba, PixFmt.Rgb48Le, PixFmt.Rgba64Le },
PixelFormatDefault = PixFmt.Rgb24,
Lossless = true,
IsImageSequence = true,
OverideExtension = "tiff",
};
}
return new EncoderInfoVideo(); return new EncoderInfoVideo();
} }
@@ -290,7 +297,7 @@ namespace Flowframes.MiscUtils
case Enums.Output.Format.Mov: return new List<Codec> { Codec.ProRes }; 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.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.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.Images: return new List<Codec> { Codec.Png, Codec.Jpeg, Codec.Webp, Codec.Tiff };
case Enums.Output.Format.Realtime: return new List<Codec> { }; case Enums.Output.Format.Realtime: return new List<Codec> { };
default: return new List<Codec> { }; default: return new List<Codec> { };
} }