using System.Runtime.CompilerServices; using Microsoft.Net.Http.Headers; namespace Encoder; public static class Utils { private static readonly Tuple[] QPTable = new Tuple[] { new(1280*720, 64), new(1920*1080, 96), new(3840*2160, 128), new(5760*2880, 96), //VR6K new(8128*4096, 120) //VR8K }.OrderBy(t => t.Item1).ToArray(); public static float Lerp(float v0, float v1, float t) { return v0 + t * (v1 - v0); } public static float Remap(float value, float from1, float to1, float from2, float to2) => from2 + (value - from1) * (to2 - from2) / (to1 - from1); public static int ToQPValue(int W, int H) { int pixels = W * H; for (var i = 0; i < QPTable.Length; i++) { if (pixels <= QPTable[i].Item1) { var minQP = QPTable[i - 1].Item2; var maxQP = QPTable[i].Item2; var minPixels = QPTable[i - 1].Item1; var maxPixels = QPTable[i].Item1; var tPixels = Remap(pixels, minPixels, maxPixels, 0, 1); return (int)Lerp(minQP, maxQP, tPixels); } } // Return the highest QP for anything higher than 8K VR return QPTable.Last().Item2; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static string AbsoluteOrProcessPath(this string path) { return Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Environment.ProcessPath)!, path)); } public static string? GetBoundary(string contentType) { var boundary = HeaderUtilities.RemoveQuotes( MediaTypeHeaderValue.Parse(contentType).Boundary ).Value; return boundary; } }