forked from renataskyfire/WebMConverter
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
190 lines (171 loc) · 6.75 KB
/
Program.cs
File metadata and controls
190 lines (171 loc) · 6.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WebMConverter
{
#region Filters
static class Filters
{
internal static CaptionFilter Caption = null;
internal static CropFilter Crop = null;
internal static DeinterlaceFilter Deinterlace = null;
internal static DenoiseFilter Denoise = null;
internal static DubFilter Dub;
internal static LevelsFilter Levels = null;
internal static MultipleTrimFilter MultipleTrim = null;
internal static OverlayFilter Overlay = null;
internal static RateFilter Rate = null;
internal static ResizeFilter Resize = null;
internal static ReverseFilter Reverse = null;
internal static SubtitleFilter Subtitle = null;
internal static TrimFilter Trim = null;
internal static void ResetFilters()
{
Caption = null;
Crop = null;
Deinterlace = null;
Denoise = null;
Dub = null;
Levels = null;
MultipleTrim = null;
Overlay = null;
Resize = null;
Reverse = null;
Subtitle = null;
Trim = null;
}
}
#endregion
static class NativeMethods
{
[DllImport("kernel32", SetLastError = true)]
public static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32", CharSet = CharSet.Auto)]
public static extern int GetShortPathName([MarshalAs(UnmanagedType.LPTStr)] string path, [MarshalAs(UnmanagedType.LPTStr)] System.Text.StringBuilder shortPath, int shortPathLength);
[DllImport("gdi32", CharSet = CharSet.Auto)]
public static extern int AddFontResourceEx(string lpszFilename, uint fl, IntPtr pdv);
[DllImport("gdi32", CharSet = CharSet.Auto)]
public static extern bool RemoveFontResourceEx(string lpFileName, uint fl, IntPtr pdv);
}
static class Program
{
public static FFMSSharp.VideoSource VideoSource;
public static FFMSSharp.ColorRange VideoColorRange;
public static bool VideoInterlaced;
public static string InputFile;
public static FileType InputType;
public static bool InputHasAudio;
public static string FileMd5;
public static string AttachmentDirectory;
public static Dictionary<int, Tuple<string, SubtitleType, string>> SubtitleTracks; // stream id, <tag:title OR codec_name, textsub/vobsub, extension>
public static List<string> AttachmentList;
const double closeenough = 0.1;
static int TimeToFrame(double time)
{
int frame = (int)((float)VideoSource.FPSNumerator / (float)VideoSource.FPSDenominator * time);
double difference;
bool? subtracted = null;
FFMSSharp.Track VideoTrack = VideoSource.Track;
FFMSSharp.FrameInfo frameinfo;
while (true)
{
frameinfo = VideoTrack.GetFrameInfo(frame);
try
{
// To convert this to a timestamp in wallclock milliseconds, use the relation int64_t timestamp = (int64_t)((FFMS_FrameInfo->PTS * FFMS_TrackTimeBase->Num) / (double)FFMS_TrackTimeBase->Den).
difference = ((frameinfo.PTS * VideoTrack.TimeBaseNumerator) / VideoTrack.TimeBaseDenominator / 1000) - time;
}
catch (NullReferenceException) // We've seeked out of bounds -- the user likely requested a time longer than the video.
{
frame = VideoTrack.NumberOfFrames - 1;
break;
}
if (Math.Abs(difference) < closeenough) break; // We've seeked close enough.
if (difference < 0)
{
if (subtracted == true) break; // This prevents us from flipping in an infinite loop, in the rare case that we can't get close enough.
frame += 1;
subtracted = false;
}
else
{
if (subtracted == false) break;
frame -= 1;
subtracted = true;
}
}
return frame;
}
internal static int TimeSpanToFrame(TimeSpan time)
{
return TimeToFrame(time.TotalSeconds);
}
static long FrameToTime(int frame)
{
var frameinfo = VideoSource.Track.GetFrameInfo(frame);
return frameinfo.PTS * VideoSource.Track.TimeBaseNumerator / VideoSource.Track.TimeBaseDenominator;
}
internal static TimeSpan FrameToTimeSpan(int frame)
{
return new TimeSpan(Program.FrameToTime(frame) * 10000);
}
internal static string FrameToTimeStamp(int frame)
{
return FrameToTimeSpan(frame).ToString(@"hh\:mm\:ss");
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// Check for AviSynth
if (NativeMethods.LoadLibrary("avisynth") == IntPtr.Zero)
{
MessageBox.Show(string.Format("Failed to load AviSynth: {0}.{1}I'll open the download page, go ahead and install it.", new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()).Message, Environment.NewLine), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
System.Diagnostics.Process.Start("http://avisynth.nl/index.php/Main_Page#Official_builds");
return;
}
// Upgrade Application Settings if applicable
if (Properties.Settings.Default.TryUpgrade)
{
Properties.Settings.Default.Upgrade();
Properties.Settings.Default.TryUpgrade = false;
Properties.Settings.Default.Save();
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
public enum FileType
{
Video,
Avisynth
}
public enum SubtitleType
{
TextSub,
VobSub
}
public static class Extensions
{
// http://stackoverflow.com/a/12179408/174466
public static void InvokeIfRequired(this ISynchronizeInvoke obj, MethodInvoker action)
{
if (obj.InvokeRequired)
{
var args = new object[0];
obj.Invoke(action, args);
}
else
{
action();
}
}
}
}