Skip to content

Commit d23e61c

Browse files
author
Etienne Charland
committed
Added unit tests
1 parent b0ae5ad commit d23e61c

File tree

84 files changed

+5495
-1100
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+5495
-1100
lines changed

ExampleApplication/ExampleApplication.csproj

+25
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="..\packages\xunit.core.2.4.1\build\xunit.core.props" Condition="Exists('..\packages\xunit.core.2.4.1\build\xunit.core.props')" />
34
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
45
<PropertyGroup>
56
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -38,6 +39,9 @@
3839
<WarningLevel>4</WarningLevel>
3940
<Prefer32Bit>false</Prefer32Bit>
4041
</PropertyGroup>
42+
<PropertyGroup>
43+
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
44+
</PropertyGroup>
4145
<ItemGroup>
4246
<Reference Include="Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
4347
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
@@ -65,6 +69,21 @@
6569
<Reference Include="WindowsBase" />
6670
<Reference Include="PresentationCore" />
6771
<Reference Include="PresentationFramework" />
72+
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
73+
<HintPath>..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll</HintPath>
74+
</Reference>
75+
<Reference Include="xunit.assert, Version=2.4.1.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
76+
<HintPath>..\packages\xunit.assert.2.4.1\lib\netstandard1.1\xunit.assert.dll</HintPath>
77+
</Reference>
78+
<Reference Include="xunit.core, Version=2.4.1.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
79+
<HintPath>..\packages\xunit.extensibility.core.2.4.1\lib\net452\xunit.core.dll</HintPath>
80+
</Reference>
81+
<Reference Include="xunit.execution.desktop, Version=2.4.1.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
82+
<HintPath>..\packages\xunit.extensibility.execution.2.4.1\lib\net452\xunit.execution.desktop.dll</HintPath>
83+
</Reference>
84+
<Reference Include="XunitDjvuTheory, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
85+
<HintPath>..\packages\XunitDjvuTheory.1.0.0\lib\net452\XunitDjvuTheory.dll</HintPath>
86+
</Reference>
6887
</ItemGroup>
6988
<ItemGroup>
7089
<ApplicationDefinition Include="App.xaml">
@@ -133,14 +152,20 @@
133152
<Name>FFmpeg</Name>
134153
</ProjectReference>
135154
</ItemGroup>
155+
<ItemGroup>
156+
<Analyzer Include="..\packages\xunit.analyzers.0.10.0\analyzers\dotnet\cs\xunit.analyzers.dll" />
157+
</ItemGroup>
136158
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
137159
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
138160
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
139161
<PropertyGroup>
140162
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
141163
</PropertyGroup>
142164
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets'))" />
165+
<Error Condition="!Exists('..\packages\xunit.core.2.4.1\build\xunit.core.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\xunit.core.2.4.1\build\xunit.core.props'))" />
166+
<Error Condition="!Exists('..\packages\xunit.core.2.4.1\build\xunit.core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\xunit.core.2.4.1\build\xunit.core.targets'))" />
143167
</Target>
168+
<Import Project="..\packages\xunit.core.2.4.1\build\xunit.core.targets" Condition="Exists('..\packages\xunit.core.2.4.1\build\xunit.core.targets')" />
144169
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
145170
Other similar extension points exist, see Microsoft.Common.targets.
146171
<Target Name="BeforeBuild">

ExampleApplication/FFmpegErrorWindow.xaml.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace EmergenceGuardian.FFmpegExampleApplication {
88
/// Interaction logic for ErrorWindow.xaml
99
/// </summary>
1010
public partial class FFmpegErrorWindow : Window {
11-
public static void Instance(Window parent, FFmpegProcess host) {
11+
public static void Instance(Window parent, IProcessManager host) {
1212
FFmpegErrorWindow F = new FFmpegErrorWindow();
1313
F.Owner = parent;
1414
F.Title = (host.LastCompletionStatus == CompletionStatus.Timeout ? "Timeout: " : "Failed: ") + host.Options.Title;

ExampleApplication/FFmpegUserInterfaceManager.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ public FFmpegUserInterfaceManager(Window parent) {
1010
this.parent = parent;
1111
}
1212

13-
public override IUserInterface CreateUI(string title, bool autoClose) {
13+
public override IUserInterfaceWindow CreateUI(string title, bool autoClose) {
1414
return Application.Current.Dispatcher.Invoke(() => FFmpegWindow.Instance(parent, title, autoClose));
1515
}
1616

17-
public override void DisplayError(FFmpegProcess host) {
17+
public override void DisplayError(IProcessManager host) {
1818
Application.Current.Dispatcher.Invoke(() => FFmpegErrorWindow.Instance(parent, host));
1919
}
2020
}

ExampleApplication/FFmpegWindow.xaml.cs

+27-23
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace EmergenceGuardian.FFmpegExampleApplication {
77
/// <summary>
88
/// Interaction logic for FFmpegWindow.xaml
99
/// </summary>
10-
public partial class FFmpegWindow : Window, IUserInterface {
10+
public partial class FFmpegWindow : Window, IUserInterfaceWindow {
1111
public static FFmpegWindow Instance(Window parent, string title, bool autoClose) {
1212
FFmpegWindow F = new FFmpegWindow();
1313
F.Owner = parent;
@@ -17,15 +17,14 @@ public static FFmpegWindow Instance(Window parent, string title, bool autoClose)
1717
return F;
1818
}
1919

20-
private FFmpegProcess host;
21-
private FFmpegProcess task;
22-
private bool autoClose;
23-
private string title { get; set; }
24-
private TimeLeftCalculator timeCalc;
20+
protected IProcessManager host;
21+
protected IProcessManagerFFmpeg hostFFmpeg;
22+
protected IProcessManager task;
23+
protected bool autoClose;
24+
protected string title { get; set; }
25+
protected ITimeLeftCalculator timeCalc;
2526

26-
public void Stop() {
27-
Dispatcher.Invoke(() => this.Close());
28-
}
27+
public void Stop() => Dispatcher.Invoke(() => this.Close());
2928

3029
public FFmpegWindow() {
3130
InitializeComponent();
@@ -35,22 +34,25 @@ private void Window_Loaded(object sender, RoutedEventArgs e) {
3534
SetPageTitle(null);
3635
}
3736

38-
public void DisplayTask(FFmpegProcess taskArg) {
37+
public void DisplayTask(IProcessManager taskArg) {
3938
Dispatcher.Invoke(() => {
4039
if (taskArg.Options.IsMainTask) {
4140
host = taskArg;
42-
host.InfoUpdated += FFmpeg_InfoUpdated;
43-
host.StatusUpdated += FFmpeg_StatusUpdated;
44-
host.Completed += FFmpeg_Completed;
41+
hostFFmpeg = host as IProcessManagerFFmpeg;
42+
if (hostFFmpeg != null) {
43+
hostFFmpeg.InfoUpdated += FFmpeg_InfoUpdated;
44+
hostFFmpeg.StatusUpdated += FFmpeg_StatusUpdated;
45+
}
46+
host.ProcessCompleted += FFmpeg_Completed;
4547
PercentText.Text = 0.ToString("p1");
4648
SetPageTitle(PercentText.Text);
4749
} else {
4850
task = taskArg;
4951
TaskStatusText.Text = task.Options.Title;
50-
task.Completed += (sender, e) => {
51-
FFmpegProcess Proc = (FFmpegProcess)sender;
52+
task.ProcessCompleted += (sender, e) => {
53+
ProcessManager Proc = (ProcessManager)sender;
5254
Dispatcher.Invoke(() => {
53-
if (e.Status == CompletionStatus.Error && !Proc.WorkProcess.StartInfo.FileName.EndsWith("avs2yuv.exe"))
55+
if (e.Status == CompletionStatus.Failed && !Proc.WorkProcess.StartInfo.FileName.EndsWith("avs2yuv.exe"))
5456
FFmpegErrorWindow.Instance(Owner, Proc);
5557
TaskStatusText.Text = "";
5658
task = null;
@@ -62,40 +64,42 @@ public void DisplayTask(FFmpegProcess taskArg) {
6264
});
6365
}
6466

67+
protected long ResumePos => hostFFmpeg.Options?.ResumePos ?? 0;
68+
6569
private void SetPageTitle(string status) {
6670
this.Title = string.IsNullOrEmpty(status) ? title : string.Format("{0} ({1})", title, status);
6771
}
6872

6973
private void FFmpeg_InfoUpdated(object sender, EventArgs e) {
7074
Dispatcher.Invoke(() => {
71-
WorkProgressBar.Maximum = host.FrameCount + host.Options.ResumePos;
72-
timeCalc = new TimeLeftCalculator(host.FrameCount + host.Options.ResumePos);
75+
WorkProgressBar.Maximum = hostFFmpeg.FrameCount + ResumePos;
76+
timeCalc = new TimeLeftCalculator(hostFFmpeg.FrameCount + hostFFmpeg?.Options.ResumePos ?? 0);
7377
});
7478
}
7579

7680
private bool EstimatedTimeLeftToggle = false;
7781
private void FFmpeg_StatusUpdated(object sender, FFmpeg.StatusUpdatedEventArgs e) {
7882
Dispatcher.Invoke(() => {
79-
WorkProgressBar.Value = e.Status.Frame + host.Options.ResumePos;
83+
WorkProgressBar.Value = e.Status.Frame + ResumePos;
8084
PercentText.Text = (WorkProgressBar.Value / WorkProgressBar.Maximum).ToString("p1");
8185
SetPageTitle(PercentText.Text);
8286
FpsText.Text = e.Status.Fps.ToString();
8387

8488
// Time left will be updated only 1 out of 2 to prevent changing too quick.
8589
EstimatedTimeLeftToggle = !EstimatedTimeLeftToggle;
8690
if (EstimatedTimeLeftToggle) {
87-
timeCalc?.Calculate(e.Status.Frame + host.Options.ResumePos);
91+
timeCalc?.Calculate(e.Status.Frame + ResumePos);
8892
TimeSpan TimeLeft = timeCalc.ResultTimeLeft;
8993
if (TimeLeft > TimeSpan.Zero)
9094
TimeLeftText.Text = TimeLeft.ToString(TimeLeft.TotalHours < 1 ? "m\\:ss" : "h\\:mm\\:ss");
9195
}
9296
});
9397
}
9498

95-
private void FFmpeg_Completed(object sender, FFmpeg.CompletedEventArgs e) {
99+
private void FFmpeg_Completed(object sender, FFmpeg.ProcessCompletedEventArgs e) {
96100
Dispatcher.Invoke(() => {
97-
FFmpegProcess Proc = sender as FFmpegProcess;
98-
if (e.Status == CompletionStatus.Error && !Proc.WorkProcess.StartInfo.FileName.EndsWith("avs2yuv.exe"))
101+
ProcessManager Proc = sender as ProcessManager;
102+
if (e.Status == CompletionStatus.Failed && !Proc.WorkProcess.StartInfo.FileName.EndsWith("avs2yuv.exe"))
99103
FFmpegErrorWindow.Instance(Owner, Proc);
100104
if (autoClose)
101105
this.Close();

ExampleApplication/MainWindow.xaml.cs

+21-16
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,17 @@ namespace EmergenceGuardian.FFmpegExampleApplication {
99
/// Interaction logic for MainWindow.xaml
1010
/// </summary>
1111
public partial class MainWindow : Window {
12+
private IUserInterfaceManager ffmpegManagerUI;
13+
private IProcessManagerFactory factory;
14+
private IMediaEncoder encoder;
15+
private IMediaMuxer muxer;
16+
1217
public MainWindow() {
1318
InitializeComponent();
14-
FFmpegConfig.FFmpegPath = @"E:\AVSMeter\ffmpeg.exe";
15-
FFmpegConfig.UserInterfaceManager = new FFmpegUserInterfaceManager(this);
19+
ffmpegManagerUI = new FFmpegUserInterfaceManager(this);
20+
factory = new ProcessManagerFactory(Properties.Settings.Default.FFmpegPath, ffmpegManagerUI);
21+
encoder = new MediaEncoder(factory);
22+
muxer = new MediaMuxer(factory);
1623

1724
//FFmpegProcess ffmpeg = new FFmpegProcess();
1825
//var status = ffmpeg.RunFFmpeg("-version");
@@ -93,11 +100,11 @@ private bool Validate() {
93100

94101
private async void RunSimpleButton_Click(object sender, RoutedEventArgs e) {
95102
if (Validate()) {
96-
ProcessStartOptions Options = new ProcessStartOptions(FFmpegDisplayMode.Interface, "Encoding to H264/AAC (Simple)");
103+
ProcessOptionsFFmpeg Options = new ProcessOptionsFFmpeg(FFmpegDisplayMode.Interface, "Encoding to H264/AAC (Simple)");
97104
string Src = SourceTextBox.Text;
98105
string Dst = DestinationTextBox.Text;
99106
await Task.Run(() => {
100-
MediaEncoder.Encode(Src, "h264", "aac", null, Dst, Options);
107+
encoder.Encode(Src, "h264", "aac", null, Dst, Options);
101108
});
102109
}
103110
}
@@ -119,20 +126,18 @@ private CompletionStatus ExecuteComplex(string src, string dst) {
119126
jobId++;
120127
CompletionStatus Result;
121128

122-
FFmpegConfig.UserInterfaceManager.Start(jobId, "Encoding to H264/AAC (Complex)");
129+
ffmpegManagerUI.Start(jobId, "Encoding to H264/AAC (Complex)");
123130

124-
ProcessStartOptions OptionsMain = new ProcessStartOptions(jobId, "", true);
125-
FFmpegProcess ProcessMain = null;
126-
OptionsMain.Started += (sender, e) => {
127-
ProcessMain = e.Process;
128-
};
129-
Task<CompletionStatus> TaskMain = Task.Run(() => MediaEncoder.Encode(src, "h264", null, "", DstEncode, OptionsMain));
131+
ProcessOptionsFFmpeg OptionsMain = new ProcessOptionsFFmpeg(jobId, "", true);
132+
IProcessManager ProcessMain = null;
133+
Task<CompletionStatus> TaskMain = Task.Run(() => encoder.Encode(src, "h264", null, "", DstEncode, OptionsMain));
130134

131-
ProcessStartOptions Options = new ProcessStartOptions(jobId, "Extracting Audio", false);
132-
Result = MediaMuxer.ExtractAudio(src, DstExtract, Options);
135+
ProcessOptionsFFmpeg Options = new ProcessOptionsFFmpeg(jobId, "Extracting Audio", false);
136+
Result = muxer.ExtractAudio(src, DstExtract, Options);
133137
if (Result == CompletionStatus.Success) {
134138
Options.Title = "Encoding Audio";
135-
Result = MediaEncoder.Encode(DstExtract, null, "aac", null, DstAac, Options);
139+
Result = encoder.Encode(DstExtract, null, "aac", null, DstAac, Options,
140+
(s, p) => ProcessMain = p.ProcessManager);
136141
}
137142

138143
if (Result != CompletionStatus.Success)
@@ -143,13 +148,13 @@ private CompletionStatus ExecuteComplex(string src, string dst) {
143148

144149
if (Result == CompletionStatus.Success && Result2 == CompletionStatus.Success) {
145150
Options.Title = "Muxing Audio and Video";
146-
Result = MediaMuxer.Muxe(DstEncode, DstAac, dst, Options);
151+
Result = muxer.Muxe(DstEncode, DstAac, dst, Options);
147152
}
148153

149154
File.Delete(DstEncode);
150155
File.Delete(DstExtract);
151156
File.Delete(DstAac);
152-
FFmpegConfig.UserInterfaceManager.Stop(jobId);
157+
ffmpegManagerUI.Stop(jobId);
153158
return Result;
154159
}
155160

ExampleApplication/Properties/Settings.Designer.cs

+13-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
<?xml version='1.0' encoding='utf-8'?>
2-
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
3-
<Profiles>
4-
<Profile Name="(Default)" />
5-
</Profiles>
6-
<Settings />
2+
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="EmergenceGuardian.FFmpegExampleApplication.Properties" GeneratedClassName="Settings">
3+
<Profiles />
4+
<Settings>
5+
<Setting Name="FFmpegPath" Type="System.String" Scope="User">
6+
<Value Profile="(Default)">E:\AVSMeter\ffmpeg.exe</Value>
7+
</Setting>
8+
</Settings>
79
</SettingsFile>

ExampleApplication/app.config

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<configuration>
3+
<configSections>
4+
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
5+
<section name="EmergenceGuardian.FFmpegExampleApplication.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
6+
</sectionGroup>
7+
</configSections>
38
<runtime>
49
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
510
<dependentAssembly>
@@ -12,4 +17,11 @@
1217
</dependentAssembly>
1318
</assemblyBinding>
1419
</runtime>
15-
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/></startup></configuration>
20+
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/></startup><userSettings>
21+
<EmergenceGuardian.FFmpegExampleApplication.Properties.Settings>
22+
<setting name="FFmpegPath" serializeAs="String">
23+
<value>E:\AVSMeter\ffmpeg.exe</value>
24+
</setting>
25+
</EmergenceGuardian.FFmpegExampleApplication.Properties.Settings>
26+
</userSettings>
27+
</configuration>

ExampleApplication/packages.config

+8
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,12 @@
33
<package id="Microsoft.Bcl" version="1.1.10" targetFramework="net461" />
44
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net461" />
55
<package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="net461" />
6+
<package id="xunit" version="2.4.1" targetFramework="net471" />
7+
<package id="xunit.abstractions" version="2.0.3" targetFramework="net471" />
8+
<package id="xunit.analyzers" version="0.10.0" targetFramework="net471" />
9+
<package id="xunit.assert" version="2.4.1" targetFramework="net471" />
10+
<package id="xunit.core" version="2.4.1" targetFramework="net471" />
11+
<package id="xunit.extensibility.core" version="2.4.1" targetFramework="net471" />
12+
<package id="xunit.extensibility.execution" version="2.4.1" targetFramework="net471" />
13+
<package id="XunitDjvuTheory" version="1.0.0" targetFramework="net471" />
614
</packages>

0 commit comments

Comments
 (0)