Files
ersatztv/ErsatzTV.FFmpeg/CommandGenerator.cs
T
Jason DoveandGitHub e8bc051f73 transcoding improvements (#1452)
* use noautoscale with vaapi encoder

* only use one input file for vaapi with radeonsi driver

* fix vaapi 8-bit to 10-bit

* fix nvidia subtitle scaling

* optimize nvidia subtitle scaling

* fix test pgs subtitle
2023-09-29 06:29:59 -05:00

104 lines
3.5 KiB
C#

using ErsatzTV.FFmpeg.Encoder;
using ErsatzTV.FFmpeg.Environment;
using ErsatzTV.FFmpeg.Filter;
using ErsatzTV.FFmpeg.GlobalOption;
using ErsatzTV.FFmpeg.InputOption;
namespace ErsatzTV.FFmpeg;
public static class CommandGenerator
{
public static IList<EnvironmentVariable> GenerateEnvironmentVariables(IEnumerable<IPipelineStep> pipelineSteps) =>
pipelineSteps.SelectMany(ps => ps.EnvironmentVariables).ToList();
public static IList<string> GenerateArguments(
Option<VideoInputFile> maybeVideoInputFile,
Option<AudioInputFile> maybeAudioInputFile,
Option<WatermarkInputFile> maybeWatermarkInputFile,
Option<ConcatInputFile> maybeConcatInputFile,
IList<IPipelineStep> pipelineSteps,
bool isIntelVaapiOrQsv)
{
var arguments = new List<string>();
foreach (IPipelineStep step in pipelineSteps)
{
arguments.AddRange(step.GlobalOptions);
}
var includedPaths = new System.Collections.Generic.HashSet<string>();
foreach (VideoInputFile videoInputFile in maybeVideoInputFile)
{
includedPaths.Add(videoInputFile.Path);
foreach (IInputOption step in videoInputFile.InputOptions)
{
arguments.AddRange(step.InputOptions(videoInputFile));
}
arguments.AddRange(new[] { "-i", videoInputFile.Path });
}
foreach (AudioInputFile audioInputFile in maybeAudioInputFile)
{
if (!includedPaths.Contains(audioInputFile.Path) || isIntelVaapiOrQsv)
{
includedPaths.Add(audioInputFile.Path);
foreach (IInputOption step in audioInputFile.InputOptions)
{
arguments.AddRange(step.InputOptions(audioInputFile));
}
arguments.AddRange(new[] { "-i", audioInputFile.Path });
}
}
foreach (WatermarkInputFile watermarkInputFile in maybeWatermarkInputFile)
{
if (!includedPaths.Contains(watermarkInputFile.Path))
{
includedPaths.Add(watermarkInputFile.Path);
foreach (IInputOption step in watermarkInputFile.InputOptions)
{
arguments.AddRange(step.InputOptions(watermarkInputFile));
}
arguments.AddRange(new[] { "-i", watermarkInputFile.Path });
}
}
foreach (ConcatInputFile concatInputFile in maybeConcatInputFile)
{
foreach (IInputOption step in concatInputFile.InputOptions)
{
arguments.AddRange(step.InputOptions(concatInputFile));
}
arguments.AddRange(new[] { "-i", concatInputFile.Path });
}
foreach (IPipelineStep step in pipelineSteps)
{
arguments.AddRange(step.FilterOptions);
}
// rearrange complex filter output options directly after video encoder
var sortedSteps = pipelineSteps.Filter(s => s is not StreamSeekFilterOption && s is not ComplexFilter).ToList();
Option<IPipelineStep> maybeComplex = pipelineSteps.Find(s => s is ComplexFilter);
foreach (IPipelineStep complex in maybeComplex)
{
int encoderIndex = sortedSteps.FindIndex(s => s is EncoderBase { Kind: StreamKind.Video });
sortedSteps.Insert(encoderIndex + 1, complex);
}
foreach (IPipelineStep step in sortedSteps)
{
arguments.AddRange(step.OutputOptions);
}
return arguments;
}
}