Skip to content

Commit

Permalink
Initial SVT-AV1 support
Browse files Browse the repository at this point in the history
Signed-off-by: akarin <[email protected]>
  • Loading branch information
AkarinVS committed Jan 29, 2023
1 parent 6547ac2 commit 179dd68
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 10 deletions.
8 changes: 8 additions & 0 deletions OKEGui/OKEGui/JobProcessor/ExceptionParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ public static ExceptionMsg Parse(OKETaskException ex, TaskDetail task)
msg.errorMsg = string.Format(Constants.x265ErrorMsg, ex.Data["X265_ERROR"], task.InputFile);
break;

case Constants.svtav1ErrorSmr:
msg.errorMsg = string.Format(Constants.svtav1ErrorMsg, ex.Data["SVTAV1_ERROR"], task.InputFile);
break;

case Constants.vpyErrorSmr:
msg.errorMsg = string.Format(Constants.vpyErrorMsg, ex.Data["VPY_ERROR"], task.InputFile);
break;
Expand All @@ -105,6 +109,10 @@ public static ExceptionMsg Parse(OKETaskException ex, TaskDetail task)
msg.errorMsg = string.Format(Constants.x265CrashMsg, task.InputFile);
break;

case Constants.svtav1CrashSmr:
msg.errorMsg = string.Format(Constants.svtav1CrashMsg, task.InputFile);
break;

case Constants.qaacErrorSmr:
msg.errorMsg = string.Format(Constants.qaacErrorMsg);
break;
Expand Down
2 changes: 1 addition & 1 deletion OKEGui/OKEGui/JobProcessor/Muxer/AutoMuxer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ private struct Episode
};

private static List<string> s_VideoFileExtensions = new List<string> {
".hevc", ".h265", ".avc", ".h264", ".mkv"
".ivf", ".hevc", ".h265", ".avc", ".h264", ".mkv"
};

private string _mkvMergePath;
Expand Down
8 changes: 5 additions & 3 deletions OKEGui/OKEGui/JobProcessor/Video/CommandlineVideoEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,16 @@ protected bool setFrameNumber(string frameString, bool isUpdateSpeed = false)
return false;
}

protected bool setSpeed(string speed)
protected bool setSpeed(string speed, string unit = "fps")
{
double fps;
double fps, factor = 1;
if (unit == "fpm")
factor = 60;
if (double.TryParse(speed, out fps))
{
if (fps > 0)
{
this.speed = fps;
this.speed = fps / factor;
}
else
{
Expand Down
143 changes: 143 additions & 0 deletions OKEGui/OKEGui/JobProcessor/Video/svtav1Encoder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using OKEGui.Utils;
using OKEGui.JobProcessor;
using System.Collections.Generic;

namespace OKEGui
{
public class SVTAV1Encoder : CommandlineVideoEncoder
{
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
private readonly string svtav1Path = "";
private readonly string vspipePath = "";
private bool expectTotalFrames = false;

public SVTAV1Encoder(VideoJob job) : base()
{
this.job = job;
getInputProperties(job);

executable = Path.Combine(Environment.SystemDirectory, "cmd.exe");

if (File.Exists(job.EncoderPath))
{
this.svtav1Path = job.EncoderPath;
}

// 获取VSPipe路径
this.vspipePath = Initializer.Config.vspipePath;

commandLine = BuildCommandline(job.EncodeParam, job.NumaNode, job.VspipeArgs);
}

public override void ProcessLine(string line, StreamType stream)
{
if (line.Contains("Svt[error]: ") || line.Contains("[SVT-Error]: ") || line.Contains("Error: "))
{
Logger.Error(line);
OKETaskException ex = new OKETaskException(Constants.svtav1ErrorSmr);
ex.progress = 0.0;
ex.Data["SVTAV1_ERROR"] = line.Substring(line.IndexOf(':')+2);
throw ex;
}

if (line.Contains("Error: fwrite() call failed when writing frame: "))
{
Logger.Error(line);
OKETaskException ex = new OKETaskException(Constants.svtav1CrashSmr);
throw ex;
}

if (line.ToLowerInvariant().Contains("all_done_encoding")) // svt-av1 must be built with -DLOG_ENC_DONE=1.
{
Logger.Debug(line);
Regex rf = new Regex("all_done_encoding *([0-9]+) frames");

var result = rf.Split(line);

ulong reportedFrames = ulong.Parse(result[1]);

Debugger.Log(0, "EncodeFinish", result[1] + " frames\n");

base.encodeFinish(reportedFrames);
}
if (line.StartsWith("Total Frames\t"))
{
Logger.Debug(line);
expectTotalFrames = true;
return;
}
if (expectTotalFrames)
{
Logger.Debug(line);
Regex rf = new Regex("[\t ]*([0-9]+)[\t ]");
var result = rf.Split(line);
if (result.Length < 2)
return;
ulong reportedFrames = ulong.Parse(result[1]);
Debugger.Log(0, "EncodeFinish", result[1] + " frames\n");
base.encodeFinish(reportedFrames);
expectTotalFrames = false;
}

Regex regOfficial = new Regex("Encoding frame *([0-9]+) *([0-9]+.[0-9]+) *kbps *([0-9]+.[0-9]+) *(fp[sm])", RegexOptions.IgnoreCase);

string[] status;

if (regOfficial.Split(line).Length >= 4)
{
status = regOfficial.Split(line);
}
else
{
Logger.Debug(line);
return;
}

if (!base.setFrameNumber(status[1], true))
{
return;
}

base.setBitrate(status[2], "kb/s");

if (!base.setSpeed(status[3], status[4]))
{
return;
}
}

private string BuildCommandline(string extractParam, int numaNode, List<string> vspipeArgs)
{
StringBuilder sb = new StringBuilder();
sb.Append("/c \"start \"foo\" /b /wait ");
if (!Initializer.Config.singleNuma)
{
sb.Append("/affinity 0xFFFFFFFFFFFFFFFF /node ");
sb.Append(numaNode.ToString());
}
// 构建vspipe参数
sb.Append(" \"" + vspipePath + "\"");
sb.Append(" --y4m");
foreach (string arg in vspipeArgs)
{
sb.Append($" --arg \"{arg}\"");
}
sb.Append(" \"" + job.Input + "\"");
sb.Append(" - |");

// 构建svtav1参数
sb.Append(" \"" + svtav1Path + "\"");
sb.Append(" --progress 2 " + extractParam + " -b");
sb.Append(" \"" + job.Output + "\" -i -");
sb.Append(" \""); // leave extra spaces for ApppendParameter.

return sb.ToString();
}

}
}
1 change: 1 addition & 0 deletions OKEGui/OKEGui/OKEGui.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
<Compile Include="JobProcessor\Demuxer\TrackInfo.cs" />
<Compile Include="JobProcessor\ExceptionParser.cs" />
<Compile Include="JobProcessor\RpChecker\RpChecker.cs" />
<Compile Include="JobProcessor\Video\svtav1Encoder.cs" />
<Compile Include="JobProcessor\Video\X264Encoder.cs" />
<Compile Include="Job\RpcJob\RpcJob.cs" />
<Compile Include="Model\Info\AudioInfo.cs" />
Expand Down
7 changes: 5 additions & 2 deletions OKEGui/OKEGui/Task/AddTaskService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public static TaskProfile ProcessJsonProfile(TaskProfile json, DirectoryInfo pro
}
}

// 编码器设置,目前只允许x264/x265
// 编码器设置,目前只允许x264/x265/svtav1
json.EncoderType = json.EncoderType.ToLower();
switch (json.EncoderType)
{
Expand All @@ -91,8 +91,11 @@ public static TaskProfile ProcessJsonProfile(TaskProfile json, DirectoryInfo pro
case "x265":
json.VideoFormat = "HEVC";
break;
case "svtav1":
json.VideoFormat = "AV1";
break;
default:
MessageBox.Show("EncoderType请填写x264或者x265", "编码器版本错误", MessageBoxButton.OK, MessageBoxImage.Error);
MessageBox.Show("EncoderType请填写x264/x265/svtav1", "编码器版本错误", MessageBoxButton.OK, MessageBoxImage.Error);
return null;
}

Expand Down
6 changes: 6 additions & 0 deletions OKEGui/OKEGui/Utils/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ public static class Constants
public const string x265ErrorMsg = "x265出错:{0}。该文件{1}将跳过处理。请转告技术总监复查。";
public const string x265ErrorSmr = "x265出错";

public const string svtav1ErrorMsg = "svt-av1出错:{0}。该文件{1}将跳过处理。请转告技术总监复查。";
public const string svtav1ErrorSmr = "svt-av1出错";

public const string vpyErrorMsg = "vpy出错:{0}。该文件{1}将跳过处理。请转告技术总监复查。";
public const string vpyErrorSmr = "vpy出错";

Expand All @@ -62,6 +65,9 @@ public static class Constants
public const string x265CrashMsg = "压制未能完成,预计是x265崩溃。该文件{0}将跳过处理,半成品以HEVC形式保留在目录中。请转告技术总监复查。";
public const string x265CrashSmr = "x265崩溃";

public const string svtav1CrashMsg = "压制未能完成,预计是svt-av1崩溃。该文件{0}将跳过处理,半成品以HEVC形式保留在目录中。请转告技术总监复查。";
public const string svtav1CrashSmr = "svt-av1崩溃";

public const string qaacErrorMsg = "QAAC无法正常运行。请确保你安装了Apple Application Support 64bit";
public const string qaacErrorSmr = "QAAC无法运行";

Expand Down
36 changes: 32 additions & 4 deletions OKEGui/OKEGui/Worker/ExecuteTaskService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ private void WorkerDoWork(object sender, DoWorkEventArgs e)
videoJob.EncodeParam += " --pools " + NumaNode.X265PoolsParam(videoJob.NumaNode);
}
}
else
else if (profile.VideoFormat == "AVC")
{
videoJob.Output = task.Taskfile.WorkingPathPrefix;
videoJob.Output += profile.ContainerFormat == "MKV" ? "_.mkv" : ".h264";
Expand All @@ -160,6 +160,18 @@ private void WorkerDoWork(object sender, DoWorkEventArgs e)
videoJob.EncodeParam += " --threads 16";
}
}
else if (profile.VideoFormat == "AV1")
{
videoJob.Output = task.Taskfile.WorkingPathPrefix + ".ivf";
if (!profile.EncoderParam.ToLower().Contains("--lp") && NumaNode.UsableCoreCount > 8)
{
videoJob.EncodeParam += " --lp 8";
}
}
else
{
throw new Exception("unknown video codec: " + profile.VideoFormat);
}

task.JobQueue.Enqueue(videoJob);

Expand Down Expand Up @@ -241,10 +253,18 @@ private void WorkerDoWork(object sender, DoWorkEventArgs e)
{
processor = new X265Encoder(vJob);
}
else
else if (vJob.CodecString == "AVC")
{
processor = new X264Encoder(vJob);
}
else if (vJob.CodecString == "AV1")
{
processor = new SVTAV1Encoder(vJob);
}
else
{
throw new Exception("unknown video codec: " + vJob.CodecString);
}

// 时间码文件
Timecode timecode = null;
Expand Down Expand Up @@ -296,8 +316,16 @@ private void WorkerDoWork(object sender, DoWorkEventArgs e)
string qpFile = vJob.Vfr
? ChapterService.GenerateQpFile(chapterInfo, timecode)
: ChapterService.GenerateQpFile(chapterInfo, vJob.Fps);
File.WriteAllText(qpFileName, qpFile);
processor.AppendParameter($"--qpfile \"{qpFileName}\"");
if (vJob.CodecString == "AV1")
{
qpFile = String.Join(",", qpFile.Replace(" I", "f").Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries));
processor.AppendParameter($"--force-key-frames \"{qpFile}\"");
}
else
{
File.WriteAllText(qpFileName, qpFile);
processor.AppendParameter($"--qpfile \"{qpFileName}\"");
}
}
else
{
Expand Down

0 comments on commit 179dd68

Please sign in to comment.