mirror of
https://github.com/revenz/FileFlowsPlugins.git
synced 2026-02-06 04:58:29 -06:00
FF-1668: New Flow Element set device
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -1,3 +1,5 @@
|
||||
using FileFlows.VideoNodes.FfmpegBuilderNodes.Models;
|
||||
|
||||
namespace FileFlows.VideoNodes.FfmpegBuilderNodes.EncoderAdjustments;
|
||||
|
||||
/// <summary>
|
||||
@@ -9,12 +11,13 @@ public class EncoderAdjustment
|
||||
/// Run any adjustments that are needed to FFmpeg arguments
|
||||
/// </summary>
|
||||
/// <param name="logger">a logger to log to</param>
|
||||
/// <param name="model">the FFmpeg Builder model</param>
|
||||
/// <param name="args">the FFmpeg args to adjust</param>
|
||||
/// <returns>the adjusted FFMpeg args</returns>
|
||||
public static List<string> Run(ILogger logger, List<string> args)
|
||||
public static List<string> Run(ILogger logger, FfmpegModel model, List<string> args)
|
||||
{
|
||||
if (VaapiAdjustments.IsUsingVaapi(args))
|
||||
return new VaapiAdjustments().Run(logger, args);
|
||||
return new VaapiAdjustments().Run(logger, model, args);
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
using FileFlows.VideoNodes.FfmpegBuilderNodes.Models;
|
||||
|
||||
namespace FileFlows.VideoNodes.FfmpegBuilderNodes.EncoderAdjustments;
|
||||
|
||||
/// <summary>
|
||||
/// Adjusts the FFmpeg commands
|
||||
/// </summary>
|
||||
public interface IEncoderAdjustment
|
||||
{
|
||||
List<string> Run(ILogger logger, List<string> args);
|
||||
/// <summary>
|
||||
/// Runs the encoder adjustments
|
||||
/// </summary>
|
||||
/// <param name="logger">the logger to use</param>
|
||||
/// <param name="model">the FFmpeg model</param>
|
||||
/// <param name="args">the FFmpeg arguments</param>
|
||||
/// <returns>the updated FFmpeg arguments</returns>
|
||||
List<string> Run(ILogger logger, FfmpegModel model, List<string> args);
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using FileFlows.VideoNodes.FfmpegBuilderNodes.Models;
|
||||
using FileFlows.VideoNodes.Helpers;
|
||||
|
||||
namespace FileFlows.VideoNodes.FfmpegBuilderNodes.EncoderAdjustments;
|
||||
@@ -18,19 +19,32 @@ public class VaapiAdjustments : IEncoderAdjustment
|
||||
/// <summary>
|
||||
/// Runt the adjustments
|
||||
/// </summary>
|
||||
/// <param name="logger">the logger to use</param>
|
||||
/// <param name="model">the ffmpeg builder model</param>
|
||||
/// <param name="args">the ffmpeg args</param>
|
||||
/// <returns>the adjusted arguments</returns>
|
||||
public List<string> Run(ILogger logger, List<string> args)
|
||||
public List<string> Run(ILogger logger, FfmpegModel? model, List<string> args)
|
||||
{
|
||||
//logger.ILog("Original VAAPI parameters: \n" + string.Join("\n", args));
|
||||
int iIndex = args.IndexOf("-i");
|
||||
if (iIndex >= 0 && VaapiHelper.VaapiLinux)
|
||||
{
|
||||
args.InsertRange(iIndex, new[]
|
||||
if (string.IsNullOrEmpty(model?.Device))
|
||||
{
|
||||
"-vaapi_device",
|
||||
VaapiHelper.VaapiRenderDevice
|
||||
});
|
||||
args.InsertRange(iIndex, new[]
|
||||
{
|
||||
"-vaapi_device",
|
||||
VaapiHelper.VaapiRenderDevice
|
||||
});
|
||||
}else if (model?.Device != "NONE")
|
||||
{
|
||||
args.InsertRange(iIndex, new[]
|
||||
{
|
||||
"-vaapi_device",
|
||||
model.Device
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// "-pix_fmt:v:{index}", "p010le", "-profile:v:{index}", "main10"
|
||||
|
||||
@@ -284,7 +284,7 @@ public class FfmpegBuilderExecutor: FfmpegBuilderNode
|
||||
}
|
||||
|
||||
var decodingParameters =
|
||||
GetHardwareDecodingArgs(args, localFile, FFMPEG, video?.Stream?.Codec, pxtFormat,
|
||||
GetHardwareDecodingArgs(args, model, localFile, FFMPEG, video?.Stream?.Codec, pxtFormat,
|
||||
encodingParameters: encodingParameters,
|
||||
inputPixelFormat: video.Stream.PixelFormat,
|
||||
destPixelFormat: targetIs10Bit ? "p010le" : (video?.Stream?.Is10Bit == false && video?.Stream?.Is12Bit == false) ? "nv12" : null);
|
||||
@@ -344,7 +344,7 @@ public class FfmpegBuilderExecutor: FfmpegBuilderNode
|
||||
}
|
||||
|
||||
// make any adjustments needed for hardware devices
|
||||
ffArgs = EncoderAdjustment.Run(args.Logger, ffArgs);
|
||||
ffArgs = EncoderAdjustment.Run(args.Logger, model, ffArgs);
|
||||
|
||||
var ffmpeg = FFMPEG;
|
||||
|
||||
@@ -427,6 +427,7 @@ public class FfmpegBuilderExecutor: FfmpegBuilderNode
|
||||
/// Gets the hardware decoder to user
|
||||
/// </summary>
|
||||
/// <param name="args">the node parameters</param>
|
||||
/// <param name="model">the FFmpeg Builder model</param>
|
||||
/// <param name="localFile">the local file</param>
|
||||
/// <param name="ffmpeg">the ffmpeg executable</param>
|
||||
/// <param name="codec">the code to use</param>
|
||||
@@ -435,7 +436,7 @@ public class FfmpegBuilderExecutor: FfmpegBuilderNode
|
||||
/// <param name="inputPixelFormat">the input pixel format of the source video</param>
|
||||
/// <param name="destPixelFormat">the true pixel format we will be encoding in</param>
|
||||
/// <returns>the hardware decoding parameters</returns>
|
||||
internal static string[] GetHardwareDecodingArgs(NodeParameters args, string localFile, string ffmpeg, string codec, string pixelFormat,
|
||||
internal static string[] GetHardwareDecodingArgs(NodeParameters args, FfmpegModel? model, string localFile, string ffmpeg, string codec, string pixelFormat,
|
||||
List<string> encodingParameters = null, string inputPixelFormat = null, string destPixelFormat = null)
|
||||
{
|
||||
var testFile = FileHelper.Combine(args.TempPath, Guid.NewGuid() + ".hwtest.mkv");
|
||||
@@ -502,7 +503,7 @@ public class FfmpegBuilderExecutor: FfmpegBuilderNode
|
||||
if (arguments.Any(x => x.Contains("vaapi", StringComparison.InvariantCultureIgnoreCase)))
|
||||
{
|
||||
args.Logger?.ILog("VAAPI detected adjusting parameters for testing");
|
||||
arguments = new VaapiAdjustments().Run(args.Logger, arguments);
|
||||
arguments = new VaapiAdjustments().Run(args.Logger, model, arguments);
|
||||
}
|
||||
|
||||
args.AdditionalInfoRecorder?.Invoke("Testing", string.Join(" ", hw), 1, new TimeSpan(0, 0, 10));
|
||||
|
||||
32
VideoNodes/FfmpegBuilderNodes/FfmpegBuilderSetDevice.cs
Normal file
32
VideoNodes/FfmpegBuilderNodes/FfmpegBuilderSetDevice.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
namespace FileFlows.VideoNodes.FfmpegBuilderNodes;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the device to use
|
||||
/// </summary>
|
||||
public class FfmpegBuilderSetDevice : FfmpegBuilderNode
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override string HelpUrl => "https://fileflows.com/docs/plugins/video-nodes/ffmpeg-builder/set-device";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int Outputs => 1;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string Icon => "fas fa-plug";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the device
|
||||
/// </summary>
|
||||
[TextVariable(1)]
|
||||
public string Device { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int Execute(NodeParameters args)
|
||||
{
|
||||
string device = args.ReplaceVariables(Device ?? string.Empty, stripMissing: true);
|
||||
args.Logger?.ILog("Device: " + device);
|
||||
|
||||
Model.Device = device?.EmptyAsNull() ?? "NONE";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -90,6 +90,11 @@
|
||||
/// </summary>
|
||||
public TimeSpan? StartTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sest the device to use
|
||||
/// </summary>
|
||||
public string? Device { get; set; }
|
||||
|
||||
internal static FfmpegModel CreateModel(VideoInfo info)
|
||||
{
|
||||
var model = new FfmpegModel(info);
|
||||
|
||||
@@ -60,8 +60,9 @@ public partial class FfmpegBuilderVideoBitrateEncode
|
||||
/// AV1 QSV encoding
|
||||
/// </summary>
|
||||
/// <param name="bitrate">the bitrate in Kbps</param>
|
||||
/// <param name="device">the device from the FFmpeg Builder Model</param>
|
||||
/// <returns>the encoding parameters</returns>
|
||||
private static IEnumerable<string> AV1_Qsv(int bitrate)
|
||||
private static IEnumerable<string> AV1_Qsv(int bitrate, string device)
|
||||
{
|
||||
var args = new List<string>
|
||||
{
|
||||
@@ -71,9 +72,14 @@ public partial class FfmpegBuilderVideoBitrateEncode
|
||||
"-maxrate", bitrate + "k",
|
||||
"-bufsize", (bitrate * 2) + "k"
|
||||
};
|
||||
if(VaapiHelper.VaapiLinux)
|
||||
args.AddRange(new [] { "-qsv_device", VaapiHelper.VaapiRenderDevice});
|
||||
|
||||
if (VaapiHelper.VaapiLinux)
|
||||
{
|
||||
if(string.IsNullOrEmpty(device))
|
||||
args.AddRange(new[] { "-qsv_device", VaapiHelper.VaapiRenderDevice });
|
||||
else if(device != "NONE")
|
||||
args.AddRange(new[] { "-qsv_device", device });
|
||||
}
|
||||
|
||||
return args.ToArray();
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,7 @@ public partial class FfmpegBuilderVideoBitrateEncode:VideoEncodeBase
|
||||
{
|
||||
bool tenBit = Codec == CODEC_AV1_10BIT || stream.Stream.Is10Bit;
|
||||
args.Logger?.ILog("10 Bit: " + tenBit);
|
||||
var encodingParameters = AV1(args, tenBit, Bitrate, encoder).ToArray();
|
||||
var encodingParameters = AV1(args, tenBit, Bitrate, encoder, Model.Device).ToArray();
|
||||
|
||||
args.Logger?.ILog("Encoding Parameters: " +
|
||||
string.Join(" ", encodingParameters.Select(x => x.Contains(" ") ? "\"" + x + "\"" : x)));
|
||||
@@ -138,14 +138,14 @@ public partial class FfmpegBuilderVideoBitrateEncode:VideoEncodeBase
|
||||
return modified.ToArray();
|
||||
}
|
||||
|
||||
internal static IEnumerable<string> GetEncodingParameters(NodeParameters args, string codec, int bitrate, string encoder, float fps)
|
||||
internal static IEnumerable<string> GetEncodingParameters(NodeParameters args, string codec, int bitrate, string encoder, float fps, string device)
|
||||
{
|
||||
if (codec == CODEC_H264)
|
||||
return H264(args, false, encoder, bitrate).Select(x => x.Replace("{index}", "0"));
|
||||
if (codec == CODEC_H265 || codec == CODEC_H265_10BIT)
|
||||
return H265(null, args, codec == CODEC_H265_10BIT, bitrate, encoder, fps).Select(x => x.Replace("{index}", "0"));
|
||||
if(codec == CODEC_AV1)
|
||||
return AV1(args, codec == CODEC_AV1_10BIT, bitrate, encoder).Select(x => x.Replace("{index}", "0"));
|
||||
return AV1(args, codec == CODEC_AV1_10BIT, bitrate, encoder, device).Select(x => x.Replace("{index}", "0"));
|
||||
|
||||
throw new Exception("Unsupported codec: " + codec);
|
||||
}
|
||||
@@ -265,7 +265,7 @@ public partial class FfmpegBuilderVideoBitrateEncode:VideoEncodeBase
|
||||
}
|
||||
|
||||
|
||||
private static IEnumerable<string> AV1(NodeParameters args, bool tenBit, int bitrate, string encoder)
|
||||
private static IEnumerable<string> AV1(NodeParameters args, bool tenBit, int bitrate, string encoder, string device)
|
||||
{
|
||||
// hevc_qsv -load_plugin hevc_hw -pix_fmt p010le -profile:v main10 -global_quality 21 -g 24 -look_ahead 1 -look_ahead_depth 60
|
||||
List<string> parameters = new List<string>();
|
||||
@@ -275,14 +275,14 @@ public partial class FfmpegBuilderVideoBitrateEncode:VideoEncodeBase
|
||||
else if(encoder == ENCODER_NVIDIA)
|
||||
parameters.AddRange(AV1_Nvidia(bitrate));
|
||||
else if(encoder == ENCODER_QSV)
|
||||
parameters.AddRange(AV1_Qsv(bitrate));
|
||||
parameters.AddRange(AV1_Qsv(bitrate, device));
|
||||
else if(encoder == ENCODER_AMF)
|
||||
parameters.AddRange(AV1_Amd(bitrate));
|
||||
|
||||
else if (CanUseHardwareEncoding.CanProcess_Nvidia_AV1(args))
|
||||
parameters.AddRange(AV1_Nvidia(bitrate));
|
||||
else if (CanUseHardwareEncoding.CanProcess_Qsv_AV1(args))
|
||||
parameters.AddRange(AV1_Qsv(bitrate));
|
||||
parameters.AddRange(AV1_Qsv(bitrate, device));
|
||||
else if (CanUseHardwareEncoding.CanProcess_Amd_AV1(args))
|
||||
parameters.AddRange(AV1_Amd(bitrate));
|
||||
else
|
||||
|
||||
@@ -85,10 +85,11 @@ public partial class FfmpegBuilderVideoEncode
|
||||
/// <summary>
|
||||
/// AV1 QSV encoding
|
||||
/// </summary>
|
||||
/// <param name="device">the device from the FFmpeg Builder model</param>
|
||||
/// <param name="quality">the quality</param>
|
||||
/// <param name="speed">the speed</param>
|
||||
/// <returns>the encoding parameters</returns>
|
||||
private static IEnumerable<string> AV1_Qsv(int quality, string speed)
|
||||
private static IEnumerable<string> AV1_Qsv(string device, int quality, string speed)
|
||||
{
|
||||
switch (speed)
|
||||
{
|
||||
@@ -109,9 +110,14 @@ public partial class FfmpegBuilderVideoEncode
|
||||
"-global_quality:v", quality.ToString(),
|
||||
"-preset", speed
|
||||
};
|
||||
if(VaapiHelper.VaapiLinux)
|
||||
args.AddRange(new [] { "-qsv_device", VaapiHelper.VaapiRenderDevice});
|
||||
|
||||
if (VaapiHelper.VaapiLinux)
|
||||
{
|
||||
if(string.IsNullOrEmpty(device))
|
||||
args.AddRange(new[] { "-qsv_device", VaapiHelper.VaapiRenderDevice });
|
||||
else if(device != "NONE")
|
||||
args.AddRange(new[] { "-qsv_device", device});
|
||||
}
|
||||
|
||||
return args.ToArray();
|
||||
}
|
||||
}
|
||||
@@ -130,7 +130,7 @@ public partial class FfmpegBuilderVideoEncode:VideoEncodeBase
|
||||
{
|
||||
bool tenBit = Codec == CODEC_AV1_10BIT || stream.Stream.Is10Bit;
|
||||
args.Logger?.ILog("10 Bit: " + tenBit);
|
||||
var encodingParameters = AV1(args, tenBit, Quality, encoder, Speed).ToArray();
|
||||
var encodingParameters = AV1(args, tenBit, Quality, encoder, Speed, Model.Device).ToArray();
|
||||
args.Logger?.ILog("Encoding Parameters: " +
|
||||
string.Join(" ", encodingParameters.Select(x => x.Contains(" ") ? "\"" + x + "\"" : x)));
|
||||
stream.EncodingParameters.AddRange(encodingParameters);
|
||||
@@ -154,14 +154,14 @@ public partial class FfmpegBuilderVideoEncode:VideoEncodeBase
|
||||
return 1;
|
||||
}
|
||||
|
||||
internal static IEnumerable<string> GetEncodingParameters(NodeParameters args, string codec, int quality, string encoder, float fps, string speed)
|
||||
internal static IEnumerable<string> GetEncodingParameters(NodeParameters args, string codec, int quality, string encoder, float fps, string speed, string? device = null)
|
||||
{
|
||||
if (codec == CODEC_H264)
|
||||
return H264(args, false, quality, encoder, speed).Select(x => x.Replace("{index}", "0"));
|
||||
if (codec == CODEC_H265 || codec == CODEC_H265_10BIT)
|
||||
return H265(null, args, codec == CODEC_H265_10BIT, quality, encoder, fps, speed).Select(x => x.Replace("{index}", "0"));
|
||||
if(codec == CODEC_AV1)
|
||||
return AV1(args, codec == CODEC_AV1_10BIT, quality, encoder, speed).Select(x => x.Replace("{index}", "0"));
|
||||
return AV1(args, codec == CODEC_AV1_10BIT, quality, encoder, speed, device).Select(x => x.Replace("{index}", "0"));
|
||||
|
||||
throw new Exception("Unsupported codec: " + codec);
|
||||
}
|
||||
@@ -281,7 +281,7 @@ public partial class FfmpegBuilderVideoEncode:VideoEncodeBase
|
||||
}
|
||||
|
||||
|
||||
private static IEnumerable<string> AV1(NodeParameters args, bool tenBit, int quality, string encoder, string speed)
|
||||
private static IEnumerable<string> AV1(NodeParameters args, bool tenBit, int quality, string encoder, string speed, string device)
|
||||
{
|
||||
// hevc_qsv -load_plugin hevc_hw -pix_fmt p010le -profile:v main10 -global_quality 21 -g 24 -look_ahead 1 -look_ahead_depth 60
|
||||
List<string> parameters = new List<string>();
|
||||
@@ -291,14 +291,14 @@ public partial class FfmpegBuilderVideoEncode:VideoEncodeBase
|
||||
else if(encoder == ENCODER_NVIDIA)
|
||||
parameters.AddRange(AV1_Nvidia(quality, speed));
|
||||
else if(encoder == ENCODER_QSV)
|
||||
parameters.AddRange(AV1_Qsv(quality, speed));
|
||||
parameters.AddRange(AV1_Qsv(device, quality, speed));
|
||||
else if(encoder == ENCODER_AMF)
|
||||
parameters.AddRange(AV1_Amd(quality, speed));
|
||||
|
||||
else if (CanUseHardwareEncoding.CanProcess_Nvidia_AV1(args))
|
||||
parameters.AddRange(AV1_Nvidia(quality, speed));
|
||||
else if (CanUseHardwareEncoding.CanProcess_Qsv_AV1(args))
|
||||
parameters.AddRange(AV1_Qsv(quality, speed));
|
||||
parameters.AddRange(AV1_Qsv(device, quality, speed));
|
||||
else if (CanUseHardwareEncoding.CanProcess_Amd_AV1(args))
|
||||
parameters.AddRange(AV1_Amd(quality, speed));
|
||||
else
|
||||
|
||||
@@ -94,7 +94,7 @@ public class VideoHasErrors: VideoNode
|
||||
if (useHardwareDecoding)
|
||||
{
|
||||
var hardwareDecodingArgs =
|
||||
FfmpegBuilderNodes.FfmpegBuilderExecutor.GetHardwareDecodingArgs(args, filename, ffmpegPath,
|
||||
FfmpegBuilderNodes.FfmpegBuilderExecutor.GetHardwareDecodingArgs(args, null, filename, ffmpegPath,
|
||||
video?.Codec, video?.PixelFormat);
|
||||
if (hardwareDecodingArgs?.Any() == true)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#if(DEBUG)
|
||||
|
||||
using FileFlows.VideoNodes.FfmpegBuilderNodes.EncoderAdjustments;
|
||||
using FileFlows.VideoNodes.FfmpegBuilderNodes.Models;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace VideoNodes.Tests;
|
||||
@@ -59,7 +60,7 @@ public class VaapiAdjustmentTests: TestBase
|
||||
};
|
||||
|
||||
var logger = new TestLogger();
|
||||
var updated = new VaapiAdjustments().Run(logger, inputParameters);
|
||||
var updated = new VaapiAdjustments().Run(logger, null!, inputParameters);
|
||||
Assert.AreEqual("-vf", updated[9]);
|
||||
Assert.AreEqual("format=nv12,hwupload,scale_vaapi=1280:-2", updated[10]);
|
||||
int index = updated.FindIndex(x => x.StartsWith("-filter:v"));
|
||||
@@ -119,7 +120,7 @@ public class VaapiAdjustmentTests: TestBase
|
||||
};
|
||||
|
||||
var logger = new TestLogger();
|
||||
var updated = new VaapiAdjustments().Run(logger, inputParameters);
|
||||
var updated = new VaapiAdjustments().Run(logger, null!, inputParameters);
|
||||
Assert.AreEqual("-vf", updated[9]);
|
||||
Assert.AreEqual("format=nv12,hwupload,scale_vaapi=1280:-2", updated[10]);
|
||||
Assert.IsFalse(updated.Any(x => x.StartsWith("-filter:v")));
|
||||
|
||||
@@ -625,6 +625,17 @@
|
||||
"Index-Help": "The index of the track to set as default, only used if language is not specified."
|
||||
}
|
||||
},
|
||||
"FfmpegBuilderSetDevice": {
|
||||
"Label": "FFMPEG Builder: Set Device",
|
||||
"Description": "Sets the device to use for hardware encoding/decoder if the encoder/decoder supports it.",
|
||||
"Outputs": {
|
||||
"1": "Device set"
|
||||
},
|
||||
"Fields": {
|
||||
"Device": "Device",
|
||||
"Device-Help": "The path to the device, or leave blank if no device should be specified."
|
||||
}
|
||||
},
|
||||
"FfmpegBuilderSetFps": {
|
||||
"Label": "FFMPEG Builder: Set FPS",
|
||||
"Description": "Set the frames per second (FPS) in the FFmpeg Builder",
|
||||
|
||||
Reference in New Issue
Block a user