add tonemap algorithm setting to ffmpeg profile (#2039)
This commit is contained in:
+2
-1
@@ -26,7 +26,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
- VAAPI may use hardware-accelerated tone mapping (when opencl accel is also available)
|
||||
- NVIDIA may use hardware-accelerated tone mapping (when vulkan accel and libplacebo filter are also available)
|
||||
- QSV may use hardware-accelerated tone mapping (when hardware decoding is used)
|
||||
- In all other cases, HDR content will use a software pipeline and the linear algorithm
|
||||
- In all other cases, HDR content will use a software pipeline
|
||||
- The tonemap algorithm can be configured in the ffmpeg profile
|
||||
- Use hardware-accelerated padding with VAAPI
|
||||
- Add environment variable `ETV_DISABLE_VULKAN`
|
||||
- Any non-empty value will disable use of Vulkan acceleration and force software tonemapping
|
||||
|
||||
@@ -21,6 +21,7 @@ public record CreateFFmpegProfile(
|
||||
FFmpegProfileBitDepth BitDepth,
|
||||
int VideoBitrate,
|
||||
int VideoBufferSize,
|
||||
FFmpegProfileTonemapAlgorithm TonemapAlgorithm,
|
||||
FFmpegProfileAudioFormat AudioFormat,
|
||||
int AudioBitrate,
|
||||
int AudioBufferSize,
|
||||
|
||||
@@ -60,6 +60,7 @@ public class CreateFFmpegProfileHandler :
|
||||
BitDepth = request.BitDepth,
|
||||
VideoBitrate = request.VideoBitrate,
|
||||
VideoBufferSize = request.VideoBufferSize,
|
||||
TonemapAlgorithm = request.TonemapAlgorithm,
|
||||
AudioFormat = request.AudioFormat,
|
||||
AudioBitrate = request.AudioBitrate,
|
||||
AudioBufferSize = request.AudioBufferSize,
|
||||
|
||||
@@ -22,6 +22,7 @@ public record UpdateFFmpegProfile(
|
||||
FFmpegProfileBitDepth BitDepth,
|
||||
int VideoBitrate,
|
||||
int VideoBufferSize,
|
||||
FFmpegProfileTonemapAlgorithm TonemapAlgorithm,
|
||||
FFmpegProfileAudioFormat AudioFormat,
|
||||
int AudioBitrate,
|
||||
int AudioBufferSize,
|
||||
|
||||
@@ -54,6 +54,7 @@ public class
|
||||
|
||||
p.VideoBitrate = update.VideoBitrate;
|
||||
p.VideoBufferSize = update.VideoBufferSize;
|
||||
p.TonemapAlgorithm = update.TonemapAlgorithm;
|
||||
p.AudioFormat = update.AudioFormat;
|
||||
p.AudioBitrate = update.AudioBitrate;
|
||||
p.AudioBufferSize = update.AudioBufferSize;
|
||||
|
||||
@@ -22,6 +22,7 @@ public record FFmpegProfileViewModel(
|
||||
FFmpegProfileBitDepth BitDepth,
|
||||
int VideoBitrate,
|
||||
int VideoBufferSize,
|
||||
FFmpegProfileTonemapAlgorithm TonemapAlgorithm,
|
||||
FFmpegProfileAudioFormat AudioFormat,
|
||||
int AudioBitrate,
|
||||
int AudioBufferSize,
|
||||
|
||||
@@ -24,6 +24,7 @@ internal static class Mapper
|
||||
profile.BitDepth,
|
||||
profile.VideoBitrate,
|
||||
profile.VideoBufferSize,
|
||||
profile.TonemapAlgorithm,
|
||||
profile.AudioFormat,
|
||||
profile.AudioBitrate,
|
||||
profile.AudioBufferSize,
|
||||
@@ -54,6 +55,7 @@ internal static class Mapper
|
||||
(int)ffmpegProfile.VideoFormat,
|
||||
ffmpegProfile.VideoBitrate,
|
||||
ffmpegProfile.VideoBufferSize,
|
||||
(int)ffmpegProfile.TonemapAlgorithm,
|
||||
(int)ffmpegProfile.AudioFormat,
|
||||
ffmpegProfile.AudioBitrate,
|
||||
ffmpegProfile.AudioBufferSize,
|
||||
|
||||
@@ -12,6 +12,7 @@ public record FFmpegFullProfileResponseModel(
|
||||
int VideoFormat,
|
||||
int VideoBitrate,
|
||||
int VideoBufferSize,
|
||||
int TonemapAlgorithm,
|
||||
int AudioFormat,
|
||||
int AudioBitrate,
|
||||
int AudioBufferSize,
|
||||
|
||||
@@ -22,6 +22,7 @@ public record FFmpegProfile
|
||||
public FFmpegProfileBitDepth BitDepth { get; set; }
|
||||
public int VideoBitrate { get; set; }
|
||||
public int VideoBufferSize { get; set; }
|
||||
public FFmpegProfileTonemapAlgorithm TonemapAlgorithm { get; set; }
|
||||
public FFmpegProfileAudioFormat AudioFormat { get; set; }
|
||||
public int AudioBitrate { get; set; }
|
||||
public int AudioBufferSize { get; set; }
|
||||
@@ -45,6 +46,7 @@ public record FFmpegProfile
|
||||
AudioFormat = FFmpegProfileAudioFormat.Aac,
|
||||
VideoBitrate = 2000,
|
||||
VideoBufferSize = 4000,
|
||||
TonemapAlgorithm = FFmpegProfileTonemapAlgorithm.Linear,
|
||||
AudioBitrate = 192,
|
||||
AudioBufferSize = 384,
|
||||
NormalizeLoudnessMode = NormalizeLoudnessMode.Off,
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace ErsatzTV.Core.Domain;
|
||||
|
||||
public enum FFmpegProfileTonemapAlgorithm
|
||||
{
|
||||
Linear = 0,
|
||||
Clip = 1,
|
||||
Gamma = 2,
|
||||
Reinhard = 3,
|
||||
Mobius = 4,
|
||||
Hable = 5
|
||||
}
|
||||
@@ -399,7 +399,8 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
|
||||
playbackSettings.ThreadCount,
|
||||
qsvExtraHardwareFrames,
|
||||
videoVersion is BackgroundImageMediaVersion { IsSongWithProgress: true },
|
||||
IsHdrTonemap: false);
|
||||
IsHdrTonemap: false,
|
||||
GetTonemapAlgorithm(playbackSettings));
|
||||
|
||||
_logger.LogDebug("FFmpeg desired state {FrameState}", desiredState);
|
||||
|
||||
@@ -554,7 +555,8 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
|
||||
Option<int>.None,
|
||||
qsvExtraHardwareFrames,
|
||||
IsSongWithProgress: false,
|
||||
IsHdrTonemap: false);
|
||||
IsHdrTonemap: false,
|
||||
GetTonemapAlgorithm(playbackSettings));
|
||||
|
||||
var ffmpegSubtitleStream = new ErsatzTV.FFmpeg.MediaStream(0, "ass", StreamKind.Video);
|
||||
|
||||
@@ -749,7 +751,8 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
|
||||
playbackSettings.ThreadCount,
|
||||
Optional(channel.FFmpegProfile.QsvExtraHardwareFrames),
|
||||
IsSongWithProgress: false,
|
||||
IsHdrTonemap: false);
|
||||
IsHdrTonemap: false,
|
||||
GetTonemapAlgorithm(playbackSettings));
|
||||
|
||||
_logger.LogDebug("FFmpeg desired state {FrameState}", desiredState);
|
||||
|
||||
@@ -1039,6 +1042,18 @@ public class FFmpegLibraryProcessService : IFFmpegProcessService
|
||||
_ => throw new ArgumentOutOfRangeException($"unexpected video format {playbackSettings.VideoFormat}")
|
||||
};
|
||||
|
||||
private static string GetTonemapAlgorithm(FFmpegPlaybackSettings playbackSettings) =>
|
||||
playbackSettings.TonemapAlgorithm switch
|
||||
{
|
||||
FFmpegProfileTonemapAlgorithm.Linear => TonemapAlgorithm.Linear,
|
||||
FFmpegProfileTonemapAlgorithm.Clip => TonemapAlgorithm.Clip,
|
||||
FFmpegProfileTonemapAlgorithm.Gamma => TonemapAlgorithm.Gamma,
|
||||
FFmpegProfileTonemapAlgorithm.Reinhard => TonemapAlgorithm.Reinhard,
|
||||
FFmpegProfileTonemapAlgorithm.Mobius => TonemapAlgorithm.Mobius,
|
||||
FFmpegProfileTonemapAlgorithm.Hable => TonemapAlgorithm.Hable,
|
||||
_ => throw new ArgumentOutOfRangeException($"unexpected tonemap algorithm {playbackSettings.TonemapAlgorithm}")
|
||||
};
|
||||
|
||||
private static Option<string> GetVideoProfile(string videoFormat, string videoProfile) =>
|
||||
(videoFormat, (videoProfile ?? string.Empty).ToLowerInvariant()) switch
|
||||
{
|
||||
|
||||
@@ -18,6 +18,7 @@ public class FFmpegPlaybackSettings
|
||||
public IPixelFormat PixelFormat { get; set; }
|
||||
public Option<int> VideoBitrate { get; set; }
|
||||
public Option<int> VideoBufferSize { get; set; }
|
||||
public FFmpegProfileTonemapAlgorithm TonemapAlgorithm { get; set; }
|
||||
public Option<int> AudioBitrate { get; set; }
|
||||
public Option<int> AudioBufferSize { get; set; }
|
||||
public Option<int> AudioChannels { get; set; }
|
||||
|
||||
@@ -116,6 +116,7 @@ public static class FFmpegPlaybackSettingsCalculator
|
||||
result.VideoFormat = ffmpegProfile.VideoFormat;
|
||||
result.VideoBitrate = ffmpegProfile.VideoBitrate;
|
||||
result.VideoBufferSize = ffmpegProfile.VideoBufferSize;
|
||||
result.TonemapAlgorithm = ffmpegProfile.TonemapAlgorithm;
|
||||
|
||||
result.VideoDecoder =
|
||||
(result.HardwareAcceleration, stream.Codec, stream.PixelFormat) switch
|
||||
@@ -184,6 +185,7 @@ public static class FFmpegPlaybackSettingsCalculator
|
||||
VideoFormat = ffmpegProfile.VideoFormat,
|
||||
VideoBitrate = ffmpegProfile.VideoBitrate,
|
||||
VideoBufferSize = ffmpegProfile.VideoBufferSize,
|
||||
TonemapAlgorithm = ffmpegProfile.TonemapAlgorithm,
|
||||
VideoDecoder = null,
|
||||
PixelFormat = ffmpegProfile.BitDepth switch
|
||||
{
|
||||
|
||||
@@ -94,7 +94,8 @@ public class PipelineBuilderBaseTests
|
||||
Option<int>.None,
|
||||
Option<int>.None,
|
||||
false,
|
||||
false);
|
||||
false,
|
||||
"clip");
|
||||
|
||||
var builder = new SoftwarePipelineBuilder(
|
||||
new DefaultFFmpegCapabilities(),
|
||||
@@ -189,7 +190,8 @@ public class PipelineBuilderBaseTests
|
||||
Option<int>.None,
|
||||
Option<int>.None,
|
||||
false,
|
||||
false);
|
||||
false,
|
||||
"clip");
|
||||
|
||||
var builder = new SoftwarePipelineBuilder(
|
||||
new DefaultFFmpegCapabilities(),
|
||||
@@ -340,7 +342,8 @@ public class PipelineBuilderBaseTests
|
||||
Option<int>.None,
|
||||
Option<int>.None,
|
||||
false,
|
||||
false);
|
||||
false,
|
||||
"clip");
|
||||
|
||||
var builder = new SoftwarePipelineBuilder(
|
||||
new DefaultFFmpegCapabilities(),
|
||||
@@ -429,7 +432,8 @@ public class PipelineBuilderBaseTests
|
||||
Option<int>.None,
|
||||
Option<int>.None,
|
||||
false,
|
||||
false);
|
||||
false,
|
||||
"clip");
|
||||
|
||||
var builder = new SoftwarePipelineBuilder(
|
||||
new DefaultFFmpegCapabilities(),
|
||||
|
||||
@@ -23,7 +23,8 @@ public record FFmpegState(
|
||||
Option<int> ThreadCount,
|
||||
Option<int> MaybeQsvExtraHardwareFrames,
|
||||
bool IsSongWithProgress,
|
||||
bool IsHdrTonemap)
|
||||
bool IsHdrTonemap,
|
||||
string TonemapAlgorithm)
|
||||
{
|
||||
public int QsvExtraHardwareFrames => MaybeQsvExtraHardwareFrames.IfNone(64);
|
||||
|
||||
@@ -49,5 +50,6 @@ public record FFmpegState(
|
||||
Option<int>.None,
|
||||
Option<int>.None,
|
||||
false,
|
||||
false);
|
||||
false,
|
||||
"linear");
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@ using ErsatzTV.FFmpeg.Format;
|
||||
|
||||
namespace ErsatzTV.FFmpeg.Filter.Cuda;
|
||||
|
||||
public class TonemapCudaFilter(IPixelFormat desiredPixelFormat) : BaseFilter
|
||||
public class TonemapCudaFilter(FFmpegState ffmpegState, IPixelFormat desiredPixelFormat) : BaseFilter
|
||||
{
|
||||
public override string Filter =>
|
||||
$"libplacebo=tonemapping=auto:colorspace=bt709:color_primaries=bt709:color_trc=bt709:format={desiredPixelFormat.FFmpegName},hwupload_cuda";
|
||||
$"libplacebo=tonemapping={ffmpegState.TonemapAlgorithm}:colorspace=bt709:color_primaries=bt709:color_trc=bt709:format={desiredPixelFormat.FFmpegName},hwupload_cuda";
|
||||
|
||||
public override FrameState NextState(FrameState currentState) =>
|
||||
currentState with
|
||||
|
||||
@@ -4,11 +4,13 @@ namespace ErsatzTV.FFmpeg.Filter;
|
||||
|
||||
public class TonemapFilter : BaseFilter
|
||||
{
|
||||
private readonly FFmpegState _ffmpegState;
|
||||
private readonly FrameState _currentState;
|
||||
private readonly IPixelFormat _desiredPixelFormat;
|
||||
|
||||
public TonemapFilter(FrameState currentState, IPixelFormat desiredPixelFormat)
|
||||
public TonemapFilter(FFmpegState ffmpegState, FrameState currentState, IPixelFormat desiredPixelFormat)
|
||||
{
|
||||
_ffmpegState = ffmpegState;
|
||||
_currentState = currentState;
|
||||
_desiredPixelFormat = desiredPixelFormat;
|
||||
}
|
||||
@@ -20,7 +22,7 @@ public class TonemapFilter : BaseFilter
|
||||
string pixelFormat = _currentState.PixelFormat.Match(pf => pf.FFmpegName, () => string.Empty);
|
||||
|
||||
var tonemap =
|
||||
$"zscale=transfer=linear,tonemap=linear,zscale=transfer=bt709,format={_desiredPixelFormat.FFmpegName}";
|
||||
$"zscale=transfer=linear,tonemap={_ffmpegState.TonemapAlgorithm},zscale=transfer=bt709,format={_desiredPixelFormat.FFmpegName}";
|
||||
|
||||
if (_currentState.FrameDataLocation == FrameDataLocation.Hardware)
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
namespace ErsatzTV.FFmpeg.Filter.Vaapi;
|
||||
|
||||
public class TonemapVaapiFilter : BaseFilter
|
||||
public class TonemapVaapiFilter(FFmpegState ffmpegState) : BaseFilter
|
||||
{
|
||||
public override string Filter => "hwupload=derive_device=vaapi,hwmap=derive_device=opencl,tonemap_opencl,hwmap=derive_device=vaapi:reverse=1";
|
||||
public override string Filter => $"hwupload=derive_device=vaapi,hwmap=derive_device=opencl,tonemap_opencl=tonemap={ffmpegState.TonemapAlgorithm},hwmap=derive_device=vaapi:reverse=1";
|
||||
|
||||
public override FrameState NextState(FrameState currentState) =>
|
||||
currentState with
|
||||
|
||||
@@ -752,14 +752,14 @@ public class NvidiaPipelineBuilder : SoftwarePipelineBuilder
|
||||
{
|
||||
if (ffmpegState.IsHdrTonemap)
|
||||
{
|
||||
var filter = new TonemapCudaFilter(pixelFormat);
|
||||
var filter = new TonemapCudaFilter(ffmpegState, pixelFormat);
|
||||
currentState = filter.NextState(currentState);
|
||||
videoStream.ResetColorParams(ColorParams.Default);
|
||||
videoInputFile.FilterSteps.Add(filter);
|
||||
}
|
||||
else
|
||||
{
|
||||
var filter = new TonemapFilter(currentState, pixelFormat);
|
||||
var filter = new TonemapFilter(ffmpegState, currentState, pixelFormat);
|
||||
currentState = filter.NextState(currentState);
|
||||
videoStream.ResetColorParams(ColorParams.Default);
|
||||
videoInputFile.FilterSteps.Add(filter);
|
||||
|
||||
@@ -660,7 +660,7 @@ public class QsvPipelineBuilder : SoftwarePipelineBuilder
|
||||
}
|
||||
else
|
||||
{
|
||||
var filter = new TonemapFilter(currentState, pixelFormat);
|
||||
var filter = new TonemapFilter(ffmpegState, currentState, pixelFormat);
|
||||
currentState = filter.NextState(currentState);
|
||||
videoStream.ResetColorParams(ColorParams.Default);
|
||||
videoInputFile.FilterSteps.Add(filter);
|
||||
|
||||
@@ -105,7 +105,7 @@ public class SoftwarePipelineBuilder : PipelineBuilderBase
|
||||
SetDeinterlace(videoInputFile, context, currentState);
|
||||
|
||||
currentState = SetScale(videoInputFile, videoStream, desiredState, currentState);
|
||||
currentState = SetTonemap(videoInputFile, videoStream, desiredState, currentState);
|
||||
currentState = SetTonemap(videoInputFile, videoStream, ffmpegState, desiredState, currentState);
|
||||
currentState = SetPad(videoInputFile, videoStream, desiredState, currentState);
|
||||
currentState = SetCrop(videoInputFile, desiredState, currentState);
|
||||
SetStillImageLoop(videoInputFile, videoStream, ffmpegState, desiredState, pipelineSteps);
|
||||
@@ -321,6 +321,7 @@ public class SoftwarePipelineBuilder : PipelineBuilderBase
|
||||
private static FrameState SetTonemap(
|
||||
VideoInputFile videoInputFile,
|
||||
VideoStream videoStream,
|
||||
FFmpegState ffmpegState,
|
||||
FrameState desiredState,
|
||||
FrameState currentState)
|
||||
{
|
||||
@@ -328,7 +329,7 @@ public class SoftwarePipelineBuilder : PipelineBuilderBase
|
||||
{
|
||||
foreach (IPixelFormat pixelFormat in desiredState.PixelFormat)
|
||||
{
|
||||
var tonemapStep = new TonemapFilter(currentState, pixelFormat);
|
||||
var tonemapStep = new TonemapFilter(ffmpegState, currentState, pixelFormat);
|
||||
currentState = tonemapStep.NextState(currentState);
|
||||
videoStream.ResetColorParams(ColorParams.Default);
|
||||
videoInputFile.FilterSteps.Add(tonemapStep);
|
||||
|
||||
@@ -638,14 +638,14 @@ public class VaapiPipelineBuilder : SoftwarePipelineBuilder
|
||||
{
|
||||
if (ffmpegState.DecoderHardwareAccelerationMode == HardwareAccelerationMode.Vaapi && _ffmpegCapabilities.HasFilter(FFmpegKnownFilter.TonemapOpenCL))
|
||||
{
|
||||
var filter = new TonemapVaapiFilter();
|
||||
var filter = new TonemapVaapiFilter(ffmpegState);
|
||||
currentState = filter.NextState(currentState);
|
||||
videoStream.ResetColorParams(ColorParams.Default);
|
||||
videoInputFile.FilterSteps.Add(filter);
|
||||
}
|
||||
else
|
||||
{
|
||||
var filter = new TonemapFilter(currentState, pixelFormat);
|
||||
var filter = new TonemapFilter(ffmpegState, currentState, pixelFormat);
|
||||
currentState = filter.NextState(currentState);
|
||||
videoStream.ResetColorParams(ColorParams.Default);
|
||||
videoInputFile.FilterSteps.Add(filter);
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace ErsatzTV.FFmpeg;
|
||||
|
||||
public static class TonemapAlgorithm
|
||||
{
|
||||
public const string Linear = "linear";
|
||||
public const string Clip = "clip";
|
||||
public const string Gamma = "gamma";
|
||||
public const string Reinhard = "reinhard";
|
||||
public const string Mobius = "mobius";
|
||||
public const string Hable = "hable";
|
||||
}
|
||||
+5884
File diff suppressed because it is too large
Load Diff
+29
@@ -0,0 +1,29 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ErsatzTV.Infrastructure.MySql.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Add_FFmpegProfile_TonemapAlgorithm : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "TonemapAlgorithm",
|
||||
table: "FFmpegProfile",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "TonemapAlgorithm",
|
||||
table: "FFmpegProfile");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -637,6 +637,9 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations
|
||||
b.Property<int>("ThreadCount")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("TonemapAlgorithm")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("VaapiDevice")
|
||||
.HasColumnType("longtext");
|
||||
|
||||
|
||||
+5723
File diff suppressed because it is too large
Load Diff
+29
@@ -0,0 +1,29 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ErsatzTV.Infrastructure.Sqlite.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Add_FFmpegProfile_TonemapAlgorithm : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "TonemapAlgorithm",
|
||||
table: "FFmpegProfile",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "TonemapAlgorithm",
|
||||
table: "FFmpegProfile");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -606,6 +606,9 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations
|
||||
b.Property<int>("ThreadCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("TonemapAlgorithm")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("VaapiDevice")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
|
||||
@@ -154,6 +154,19 @@
|
||||
<MudTextField Disabled="@(_model.HardwareAcceleration != HardwareAccelerationKind.Qsv)" Label="QSV Extra Hardware Frames" @bind-Value="_model.QsvExtraHardwareFrames" For="@(() => _model.QsvExtraHardwareFrames)"/>
|
||||
</MudElement>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudElement HtmlTag="div" Class="mt-3">
|
||||
<MudSelect Label="Tonemap Algorithm"
|
||||
@bind-Value="_model.TonemapAlgorithm"
|
||||
For="@(() => _model.TonemapAlgorithm)">
|
||||
@foreach (FFmpegProfileTonemapAlgorithm algorithm in Enum.GetValues<FFmpegProfileTonemapAlgorithm>())
|
||||
{
|
||||
<MudSelectItem Value="@algorithm">@algorithm</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
</MudElement>
|
||||
}
|
||||
<MudElement HtmlTag="div" Class="mt-3">
|
||||
<MudCheckBox Label="Normalize Frame Rate" @bind-Value="@_model.NormalizeFramerate" For="@(() => _model.NormalizeFramerate)"/>
|
||||
</MudElement>
|
||||
|
||||
@@ -38,6 +38,7 @@ public class FFmpegProfileEditViewModel
|
||||
VideoPreset = viewModel.VideoPreset;
|
||||
AllowBFrames = viewModel.AllowBFrames;
|
||||
BitDepth = viewModel.BitDepth;
|
||||
TonemapAlgorithm = viewModel.TonemapAlgorithm;
|
||||
}
|
||||
|
||||
public int AudioBitrate { get; set; }
|
||||
@@ -65,6 +66,7 @@ public class FFmpegProfileEditViewModel
|
||||
public string VideoPreset { get; set; }
|
||||
public bool AllowBFrames { get; set; }
|
||||
public FFmpegProfileBitDepth BitDepth { get; set; }
|
||||
public FFmpegProfileTonemapAlgorithm TonemapAlgorithm { get; set; }
|
||||
|
||||
public CreateFFmpegProfile ToCreate() =>
|
||||
new(
|
||||
@@ -84,6 +86,7 @@ public class FFmpegProfileEditViewModel
|
||||
BitDepth,
|
||||
VideoBitrate,
|
||||
VideoBufferSize,
|
||||
TonemapAlgorithm,
|
||||
AudioFormat,
|
||||
AudioBitrate,
|
||||
AudioBufferSize,
|
||||
@@ -113,6 +116,7 @@ public class FFmpegProfileEditViewModel
|
||||
BitDepth,
|
||||
VideoBitrate,
|
||||
VideoBufferSize,
|
||||
TonemapAlgorithm,
|
||||
AudioFormat,
|
||||
AudioBitrate,
|
||||
AudioBufferSize,
|
||||
|
||||
Reference in New Issue
Block a user