Skip to content

Commit

Permalink
Add Target VMAF (#140)
Browse files Browse the repository at this point in the history
* Target VMAF Base (POC - unfinished)

* Fix Input Seeeking Frane Inaccuracy (Scene Based Splitting)

* Fix Target VMAF
Make Target VMAF more reliable

* Add Target VMAF Front-end options

* Target VMAF UI Translations
  • Loading branch information
Alkl58 authored Mar 26, 2023
1 parent 3e65640 commit 1776039
Show file tree
Hide file tree
Showing 17 changed files with 915 additions and 115 deletions.
31 changes: 24 additions & 7 deletions NotEnoughAV1Encodes/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -367,21 +367,38 @@
</Style>
</Canvas.Style>
<Slider x:Name="SliderQualityAOMFFMPEG" Value="{Binding AOMFFMPEGQuantizer}" VerticalAlignment="Top" SmallChange="1" Maximum="63" TickPlacement="BottomRight" Height="34" IsSnapToTickEnabled="True" Canvas.Left="131" Canvas.Top="69" Width="520"/>
<Label Content="{Binding ElementName=SliderQualityAOMFFMPEG, Path=Value, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" HorizontalAlignment="Right" Width="78" Canvas.Left="664" Canvas.Top="75"/>
<Label x:Name="LabelQuantizerPreview" Content="{Binding ElementName=SliderQualityAOMFFMPEG, Path=Value, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" HorizontalAlignment="Right" Width="78" Canvas.Left="664" Canvas.Top="75"/>
<Label x:Name="LabelQualityMode" Content="{lex:Loc}" HorizontalAlignment="Left" Margin="18,12,0,0" VerticalAlignment="Top" Width="108"/>
<ComboBox x:Name="ComboBoxQualityMode" SelectedIndex="{Binding AOMFFMPEGQualityMode}" HorizontalAlignment="Left" Margin="131,10,0,0" VerticalAlignment="Top" Width="140" Height="30" SelectionChanged="ComboBoxQualityMode_SelectionChanged">
<ComboBoxItem Content="Constant Quality"/>
<ComboBoxItem Content="Constrained Quality"/>
<ComboBoxItem Content="Average Bitrate"/>
<ComboBoxItem Content="Constrained Bitrate"/>
<ComboBoxItem Content="Target VMAF"/>
</ComboBox>
<Label x:Name="LabelQuantizer" Content="{lex:Loc}" HorizontalAlignment="Left" Margin="20,73,0,0" VerticalAlignment="Top" Width="106" Height="30"/>
<Label x:Name="LabelBitrateMin" Content="{lex:Loc}" Visibility="{Binding ElementName=TextBoxMinBitrateAOMFFMPEG, Path=Visibility, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding ElementName=TextBoxMinBitrateAOMFFMPEG, Path=IsEnabled, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="21,140,0,0" VerticalAlignment="Top" Width="106" Height="30"/>
<Label x:Name="LabelBitrateAvg" Content="{lex:Loc}" IsEnabled="{Binding ElementName=TextBoxAVGBitrateAOMFFMPEG, Path=IsEnabled, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="21,173,0,0" VerticalAlignment="Top" Width="105" Height="30"/>
<Label x:Name="LabelBitrateMax" Content="{lex:Loc}" Visibility="{Binding ElementName=TextBoxMaxBitrateAOMFFMPEG, Path=Visibility, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding ElementName=TextBoxMaxBitrateAOMFFMPEG, Path=IsEnabled, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="21,206,0,0" VerticalAlignment="Top" Width="105" Height="30"/>
<TextBox x:Name="TextBoxMinBitrateAOMFFMPEG" PreviewTextInput="NumberValidationTextBox" Margin="131,142,0,0" Text="{Binding AOMFFMPEGMinBitrate}" TextWrapping="Wrap" VerticalAlignment="Top" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" IsEnabled="False" HorizontalAlignment="Left" Width="120"/>
<TextBox x:Name="TextBoxAVGBitrateAOMFFMPEG" PreviewTextInput="NumberValidationTextBox" Margin="131,175,0,0" Text="{Binding AOMFFMPEGAvgBitrate}" TextWrapping="Wrap" VerticalAlignment="Top" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" IsEnabled="False" HorizontalAlignment="Left" Width="120"/>
<TextBox x:Name="TextBoxMaxBitrateAOMFFMPEG" PreviewTextInput="NumberValidationTextBox" Margin="131,208,0,0" Text="{Binding AOMFFMPEGMaxBitrate}" TextWrapping="Wrap" VerticalAlignment="Top" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" IsEnabled="False" HorizontalAlignment="Left" Width="120"/>
<Label x:Name="LabelBitrateMin" Content="{lex:Loc}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="106" Height="30" Canvas.Left="21" Canvas.Top="46"/>
<Label x:Name="LabelBitrateAvg" Content="{lex:Loc}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="105" Height="30" Canvas.Left="21" Canvas.Top="79"/>
<Label x:Name="LabelBitrateMax" Content="{lex:Loc}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="105" Height="30" Canvas.Left="21" Canvas.Top="112"/>
<TextBox x:Name="TextBoxMinBitrateAOMFFMPEG" PreviewTextInput="NumberValidationTextBox" Text="{Binding AOMFFMPEGMinBitrate}" TextWrapping="Wrap" VerticalAlignment="Top" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" HorizontalAlignment="Left" Width="120" Canvas.Left="131" Canvas.Top="48"/>
<TextBox x:Name="TextBoxAVGBitrateAOMFFMPEG" PreviewTextInput="NumberValidationTextBox" Text="{Binding AOMFFMPEGAvgBitrate}" TextWrapping="Wrap" VerticalAlignment="Top" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" HorizontalAlignment="Left" Width="120" Canvas.Left="131" Canvas.Top="81"/>
<TextBox x:Name="TextBoxMaxBitrateAOMFFMPEG" PreviewTextInput="NumberValidationTextBox" Text="{Binding AOMFFMPEGMaxBitrate}" TextWrapping="Wrap" VerticalAlignment="Top" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" HorizontalAlignment="Left" Width="120" Canvas.Left="131" Canvas.Top="114"/>
<!-- Target VMAF -->
<Label x:Name="LabelTargetVMAF" Content="{lex:Loc}" HorizontalAlignment="Left" VerticalAlignment="Center" Width="106" Height="30" Canvas.Left="18" Canvas.Top="46"/>
<Slider x:Name="SliderTargetVMAF" Value="{Binding TargetVMAFScore}" VerticalAlignment="Top" SmallChange="0.5" Maximum="100" TickPlacement="BottomRight" Height="34" IsSnapToTickEnabled="True" Canvas.Left="132" Canvas.Top="42" Width="520" Minimum="70" TickFrequency="0.5"/>
<Label x:Name="LabelTargetVMAFPreview" Content="{Binding ElementName=SliderTargetVMAF, Path=Value, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" HorizontalAlignment="Center" Width="78" Canvas.Left="664" Canvas.Top="46"/>
<Label x:Name="LabelTargetVMAFProbes" Content="{lex:Loc}" HorizontalAlignment="Center" VerticalAlignment="Top" Width="106" Height="30" Canvas.Left="18" Canvas.Top="79"/>
<Slider x:Name="SliderTargetVMAFProbes" Value="{Binding TargetVMAFProbes}" VerticalAlignment="Center" SmallChange="1" Maximum="6" TickPlacement="BottomRight" Height="34" IsSnapToTickEnabled="True" Canvas.Left="132" Canvas.Top="73" Width="520" Minimum="2" TickFrequency="1" HorizontalAlignment="Center" ToolTip="{lex:Loc SliderTargetVMAFProbesToolTip}"/>
<Label x:Name="LabelTargetVMAFProbesPreview" Content="{Binding ElementName=SliderTargetVMAFProbes, Path=Value, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" HorizontalAlignment="Left" Width="78" Canvas.Left="664" Canvas.Top="77"/>
<Label x:Name="LabelTargetVMAFMinQ" Content="{lex:Loc}" HorizontalAlignment="Center" VerticalAlignment="Top" Width="106" Height="30" Canvas.Left="18" Canvas.Top="109"/>
<Slider x:Name="SliderTargetVMAFMinQ" Value="{Binding TargetVMAFMinQ}" VerticalAlignment="Top" SmallChange="1" Maximum="63" TickPlacement="BottomRight" Height="34" IsSnapToTickEnabled="True" Canvas.Left="132" Canvas.Top="103" Width="520" ValueChanged="SliderTargetVMAFMinQ_ValueChanged" ToolTip="{lex:Loc SliderTargetVMAFMinQToolTip}"/>
<Label x:Name="LabelTargetVMAFMinQPreview" Content="{Binding ElementName=SliderTargetVMAFMinQ, Path=Value, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" HorizontalAlignment="Center" Width="78" Canvas.Left="664" Canvas.Top="107"/>
<Label x:Name="LabelTargetVMAFMaxQ" Content="{lex:Loc}" HorizontalAlignment="Center" VerticalAlignment="Top" Width="106" Height="30" Canvas.Left="18" Canvas.Top="137"/>
<Slider x:Name="SliderTargetVMAFMaxQ" Value="{Binding TargetVMAFMaxQ}" VerticalAlignment="Top" SmallChange="1" Maximum="63" TickPlacement="BottomRight" Height="34" IsSnapToTickEnabled="True" Canvas.Left="132" Canvas.Top="133" Width="520" HorizontalAlignment="Center" ValueChanged="SliderTargetVMAFMaxQ_ValueChanged" ToolTip="{lex:Loc SliderTargetVMAFMaxQToolTip}"/>
<Label x:Name="LabelTargetVMAFMaxQPreview" Content="{Binding ElementName=SliderTargetVMAFMaxQ, Path=Value, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" HorizontalAlignment="Center" Width="78" Canvas.Left="664" Canvas.Top="138"/>
<Label x:Name="LabelTargetVMAFMaxProbeLength" Content="{lex:Loc}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="106" Height="30" Canvas.Left="19" Canvas.Top="167"/>
<Slider x:Name="SliderTargetVMAFMaxProbeLength" Value="{Binding TargetVMAFProbeLength}" VerticalAlignment="Top" SmallChange="1" Maximum="60" TickPlacement="BottomRight" Height="34" IsSnapToTickEnabled="True" Canvas.Left="132" Canvas.Top="165" Width="520" HorizontalAlignment="Center" ToolTip="{lex:Loc SliderTargetVMAFMaxProbeLengthToolTip}" Minimum="1"/>
<Label x:Name="LabelTargetVMAFMaxProbeLengthPreview" Content="{Binding ElementName=SliderTargetVMAFMaxProbeLength, Path=Value, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" HorizontalAlignment="Center" Width="78" Canvas.Left="664" Canvas.Top="169"/>
</Canvas>
<!-- RAV1E FFmpeg -->
<Canvas HorizontalAlignment="Left" Width="1055">
Expand Down
104 changes: 87 additions & 17 deletions NotEnoughAV1Encodes/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -996,33 +996,102 @@ private void ComboBoxVideoEncoder_SelectionChanged(object sender, System.Windows

private void ComboBoxQualityMode_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
// Hide all
LabelQuantizer.Visibility = Visibility.Collapsed;
SliderQualityAOMFFMPEG.Visibility = Visibility.Collapsed;
LabelQuantizerPreview.Visibility = Visibility.Collapsed;
LabelBitrateMin.Visibility = Visibility.Collapsed;
TextBoxMinBitrateAOMFFMPEG.Visibility = Visibility.Collapsed;
LabelBitrateAvg.Visibility = Visibility.Collapsed;
TextBoxAVGBitrateAOMFFMPEG.Visibility = Visibility.Collapsed;
LabelBitrateMax.Visibility = Visibility.Collapsed;
TextBoxMaxBitrateAOMFFMPEG.Visibility = Visibility.Collapsed;
LabelTargetVMAF.Visibility = Visibility.Collapsed;
LabelTargetVMAFPreview.Visibility = Visibility.Collapsed;
SliderTargetVMAF.Visibility = Visibility.Collapsed;
LabelTargetVMAFProbes.Visibility = Visibility.Collapsed;
SliderTargetVMAFProbes.Visibility = Visibility.Collapsed;
LabelTargetVMAFProbesPreview.Visibility = Visibility.Collapsed;
LabelTargetVMAFMinQ.Visibility = Visibility.Collapsed;
SliderTargetVMAFMinQ.Visibility= Visibility.Collapsed;
LabelTargetVMAFMinQPreview.Visibility = Visibility.Collapsed;
LabelTargetVMAFMaxQ.Visibility = Visibility.Collapsed;
SliderTargetVMAFMaxQ.Visibility = Visibility.Collapsed;
LabelTargetVMAFMaxQPreview.Visibility = Visibility.Collapsed;
LabelTargetVMAFMaxProbeLength.Visibility = Visibility.Collapsed;
SliderTargetVMAFMaxProbeLength.Visibility = Visibility.Collapsed;
LabelTargetVMAFMaxProbeLengthPreview.Visibility = Visibility.Collapsed;
PresetSettings.TargetVMAF = false;

if (ComboBoxQualityMode.SelectedIndex == 0)
{
SliderQualityAOMFFMPEG.IsEnabled = true;
TextBoxAVGBitrateAOMFFMPEG.IsEnabled = false;
TextBoxMaxBitrateAOMFFMPEG.IsEnabled = false;
TextBoxMinBitrateAOMFFMPEG.IsEnabled = false;
// Constant Quality
LabelQuantizer.Visibility = Visibility.Visible;
SliderQualityAOMFFMPEG.Visibility = Visibility.Visible;
LabelQuantizerPreview.Visibility = Visibility.Visible;
}
else if (ComboBoxQualityMode.SelectedIndex == 1)
{
SliderQualityAOMFFMPEG.IsEnabled = true;
TextBoxAVGBitrateAOMFFMPEG.IsEnabled = false;
TextBoxMaxBitrateAOMFFMPEG.IsEnabled = true;
TextBoxMinBitrateAOMFFMPEG.IsEnabled = false;
// Constrained Quality
TextBoxMaxBitrateAOMFFMPEG.Visibility = Visibility.Visible;
LabelBitrateMax.Visibility = Visibility.Visible;
LabelQuantizer.Visibility = Visibility.Visible;
SliderQualityAOMFFMPEG.Visibility = Visibility.Visible;
LabelQuantizerPreview.Visibility = Visibility.Visible;
}
else if (ComboBoxQualityMode.SelectedIndex == 2)
{
SliderQualityAOMFFMPEG.IsEnabled = false;
TextBoxAVGBitrateAOMFFMPEG.IsEnabled = true;
TextBoxMaxBitrateAOMFFMPEG.IsEnabled = false;
TextBoxMinBitrateAOMFFMPEG.IsEnabled = false;
// Average Bitrate
LabelBitrateAvg.Visibility = Visibility.Visible;
TextBoxAVGBitrateAOMFFMPEG.Visibility = Visibility.Visible;
}
else if (ComboBoxQualityMode.SelectedIndex == 3)
{
SliderQualityAOMFFMPEG.IsEnabled = false;
TextBoxAVGBitrateAOMFFMPEG.IsEnabled = true;
TextBoxMaxBitrateAOMFFMPEG.IsEnabled = true;
TextBoxMinBitrateAOMFFMPEG.IsEnabled = true;
// Constrained Bitrate
LabelBitrateMin.Visibility = Visibility.Visible;
TextBoxMinBitrateAOMFFMPEG.Visibility = Visibility.Visible;
LabelBitrateAvg.Visibility = Visibility.Visible;
TextBoxAVGBitrateAOMFFMPEG.Visibility = Visibility.Visible;
LabelBitrateMax.Visibility = Visibility.Visible;
TextBoxMaxBitrateAOMFFMPEG.Visibility = Visibility.Visible;
}
else if (ComboBoxQualityMode.SelectedIndex == 4)
{
// Target VMAF
PresetSettings.TargetVMAF = true;
LabelTargetVMAF.Visibility = Visibility.Visible;
LabelTargetVMAFPreview.Visibility = Visibility.Visible;
SliderTargetVMAF.Visibility = Visibility.Visible;
LabelTargetVMAFProbes.Visibility = Visibility.Visible;
SliderTargetVMAFProbes.Visibility = Visibility.Visible;
LabelTargetVMAFProbesPreview.Visibility = Visibility.Visible;
LabelTargetVMAFMinQ.Visibility = Visibility.Visible;
SliderTargetVMAFMinQ.Visibility = Visibility.Visible;
LabelTargetVMAFMinQPreview.Visibility = Visibility.Visible;
LabelTargetVMAFMaxQ.Visibility = Visibility.Visible;
SliderTargetVMAFMaxQ.Visibility = Visibility.Visible;
LabelTargetVMAFMaxQPreview.Visibility = Visibility.Visible;
LabelTargetVMAFMaxProbeLength.Visibility = Visibility.Visible;
SliderTargetVMAFMaxProbeLength.Visibility = Visibility.Visible;
LabelTargetVMAFMaxProbeLengthPreview.Visibility = Visibility.Visible;
}
}

private void SliderTargetVMAFMinQ_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (SliderTargetVMAF == null) return;
if (SliderTargetVMAFMinQ.Value > SliderTargetVMAFMaxQ.Value)
{
SliderTargetVMAFMaxQ.Value = SliderTargetVMAFMinQ.Value;
}
}

private void SliderTargetVMAFMaxQ_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (SliderTargetVMAF == null) return;
if (SliderTargetVMAFMinQ.Value > SliderTargetVMAFMaxQ.Value)
{
SliderTargetVMAFMinQ.Value = SliderTargetVMAFMaxQ.Value;
}
}

Expand Down Expand Up @@ -2027,6 +2096,7 @@ private string GenerateAomFFmpegCommand()
1 => " -crf " + SliderQualityAOMFFMPEG.Value + " -b:v " + TextBoxMaxBitrateAOMFFMPEG.Text + "k",
2 => " -b:v " + TextBoxMinBitrateAOMFFMPEG.Text + "k",
3 => " -minrate " + TextBoxMinBitrateAOMFFMPEG.Text + "k -b:v " + TextBoxAVGBitrateAOMFFMPEG.Text + "k -maxrate " + TextBoxMaxBitrateAOMFFMPEG.Text + "k",
4 => " -crf {q_vmaf} -b:v 0",
_ => ""
};

Expand Down Expand Up @@ -2732,7 +2802,7 @@ private async Task MainStartAsync(CancellationToken _cancelToken)
{
await Task.Run(() => videoSplitter.Split(queueElement, _cancelToken), _cancelToken);
if (queueElement.ChunkingMethod == 0)
if (queueElement.ChunkingMethod == 0 || queueElement.Preset.TargetVMAF)
{
// Equal Chunking
IOrderedEnumerable<string> sortedChunks = Directory.GetFiles(Path.Combine(Global.Temp, "NEAV1E", queueElement.UniqueIdentifier, "Chunks"), "*.mkv", SearchOption.TopDirectoryOnly).OrderBy(f => f);
Expand Down
1 change: 1 addition & 0 deletions NotEnoughAV1Encodes/NotEnoughAV1Encodes.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

<ItemGroup>
<PackageReference Include="MahApps.Metro" Version="2.4.9" />
<PackageReference Include="MathNet.Numerics" Version="5.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="Octokit" Version="5.0.0" />
<PackageReference Include="System.Management" Version="7.0.0" />
Expand Down
13 changes: 13 additions & 0 deletions NotEnoughAV1Encodes/Queue/ChunkVMAF.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Collections.Generic;
using System.Windows.Documents;

namespace NotEnoughAV1Encodes.Queue
{
public class ChunkVMAF
{
public string ChunkName { get; set; }
public string CalculatedQuantizer { get; set; }
public List<double> QValues { get; set; }
public List<double> VMAFValues { get; set; }
}
}
2 changes: 2 additions & 0 deletions NotEnoughAV1Encodes/Queue/QueueElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public string Status
public string VideoCommand { get; set; }
/// <summary>Video HDR Muxing parameters.</summary>
public string VideoHDRMuxCommand { get; set; }
/// <summary>Target VMAF Chunk List.</summary>
public List<ChunkVMAF> ChunkVMAF { get; set; } = new();
/// <summary>Audio Encoding parameters.</summary>
public string AudioCommand { get; set; }
/// <summary>Softsub Command</summary>
Expand Down
Loading

0 comments on commit 1776039

Please sign in to comment.