-
Notifications
You must be signed in to change notification settings - Fork 0
/
AVIFile.vb
274 lines (223 loc) · 9.14 KB
/
AVIFile.vb
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
Imports System.Runtime.InteropServices
Imports System.Reflection
Imports System.IO
Imports System.Drawing
Public Class AVIFile
Implements IDisposable
Private AviFile As IntPtr
Private FrameObject As IntPtr
Private AviStream As IntPtr
Private StreamInfo As _AVISTREAMINFO
Private Sourcefile As String
Sub New(path As String)
Try
Sourcefile = path
AVIFileInit()
Const OF_SHARE_DENY_WRITE = 32
If AVIFileOpen(AviFile, path, OF_SHARE_DENY_WRITE, IntPtr.Zero) <> 0 Then
ThrowException("AVIFileOpen failed to execute")
End If
If AVIFileGetStream(AviFile, AviStream, mmioStringToFOURCC("vids", 0), 0) <> 0 Then 'FourCC for vids
ThrowException("AVIFileGetStream failed to execute")
End If
FrameCountValue = AVIStreamLength(AviStream)
If FrameCountValue = 240 Then
Dim clipInfo = TryCast(Marshal.GetObjectForIUnknown(AviFile), IAvisynthClipInfo)
If Not clipInfo Is Nothing Then
Dim ptr As IntPtr
If clipInfo.GetError(ptr) = 0 Then ErrorMessageValue = Marshal.PtrToStringAnsi(ptr)
Marshal.ReleaseComObject(clipInfo)
End If
Else
ErrorMessageValue = Nothing
End If
StreamInfo = New _AVISTREAMINFO()
If AVIStreamInfo(AviStream, StreamInfo, Marshal.SizeOf(StreamInfo)) <> 0 Then
ThrowException("AVIStreamInfo failed to execute")
End If
Catch ex As Exception
Dispose()
WriteLog()
Throw ex
End Try
End Sub
Sub ThrowException(message As String)
If Sourcefile.Ext = "avs" Then
Throw New Exception(message + BR2 + "Failed to open AviSynth script:" + BR2 + Sourcefile + BR2 + "You can try to open the script with VirtualDub x64, if it don't open it could be a problem with the script or the AviSynth+ x64 setup, if StaxRip don't report a script error and the script looks valid then reinstalling AviSynth+ x64 might fix the problem, the setup is located at:" + BR2 + Folder.Apps)
Else
Throw New Exception(message + BR2 + "Failed to open script:" + BR2 + Sourcefile)
End If
End Sub
Private FrameCountValue As Integer
ReadOnly Property FrameCount As Integer
Get
Return FrameCountValue
End Get
End Property
ReadOnly Property FrameRate() As Double
Get
Return StreamInfo.dwRate / StreamInfo.dwScale
End Get
End Property
ReadOnly Property FrameSize() As Size
Get
Return New Size(CInt(StreamInfo.rcFrame.Right), CInt(StreamInfo.rcFrame.Bottom))
End Get
End Property
Private ErrorMessageValue As String
ReadOnly Property ErrorMessage() As String
Get
Return ErrorMessageValue
End Get
End Property
Private PositionValue As Integer
Property Position As Integer
Get
Return PositionValue
End Get
Set(value As Integer)
If value < 0 Then
PositionValue = 0
ElseIf value > FrameCount - 1 Then
PositionValue = FrameCount - 1
Else
PositionValue = value
End If
End Set
End Property
Sub WriteLog()
'Log.WriteHeader("Script file failed to load")
'Log.WriteLine("Source File Path: " + Sourcefile)
'Try
' Log.WriteLine(File.ReadAllText(Sourcefile) + BR)
'Catch ex As Exception
' MsgBox("Failed to read script file", ex.Message)
' 'Throw New ErrorAbortException("Failed to read script file", ex.Message)
'End Try
'If Directory.Exists(Folder.Plugins) Then
' Log.WriteLine("Plugins: " + Directory.GetFiles(Folder.Plugins, "*.dll").Join(", ").Replace(Folder.Plugins, "").Replace(".dll", ""))
'Else
' Log.WriteLine("Plugin directory is missing!")
'End If
End Sub
Function GetDIB() As IntPtr
If FrameObject = IntPtr.Zero Then
Const AVIGETFRAMEF_BESTDISPLAYFMT = 1
FrameObject = AVIStreamGetFrameOpen(AviStream, AVIGETFRAMEF_BESTDISPLAYFMT)
If FrameObject = IntPtr.Zero Then FrameObject = AVIStreamGetFrameOpen(AviStream, 0)
End If
If FrameObject <> IntPtr.Zero Then Return AVIStreamGetFrame(FrameObject, Position)
End Function
Function GetBitmap() As Bitmap
Dim dib = GetDIB()
If dib <> IntPtr.Zero Then Return GetBMPFromDib(dib)
End Function
Private Function GetBMPFromDib(pDIB As IntPtr) As Bitmap
Dim pPix As New IntPtr(pDIB.ToInt64 + Marshal.SizeOf(GetType(BITMAPINFOHEADER)))
Dim mi = GetType(Bitmap).GetMethod("FromGDIplus", BindingFlags.Static Or BindingFlags.NonPublic)
Dim pBmp = IntPtr.Zero
GdipCreateBitmapFromGdiDib(pDIB, pPix, pBmp)
Return DirectCast(mi.Invoke(Nothing, {pBmp}), Bitmap)
End Function
<Guid("E6D6B708-124D-11D4-86F3-DB80AFD98778"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
Private Interface IAvisynthClipInfo
Function GetError(ByRef msg As IntPtr) As Integer
Function GetParity(value As Integer) As Byte
Function IsFieldBased() As Byte
End Interface
<DllImport("gdiplus.dll")>
Private Shared Function GdipCreateBitmapFromGdiDib(bminfo As IntPtr, pixdat As IntPtr, ByRef image As IntPtr) As Integer
End Function
<DllImport("avifil32.dll")>
Private Shared Sub AVIFileInit()
End Sub
<DllImport("avifil32.dll", CharSet:=CharSet.Unicode)>
Private Shared Function AVIFileOpen(ByRef ppfile As IntPtr, szFile As String, uMode As Integer, pclsidHandler As IntPtr) As Integer
End Function
<DllImport("avifil32.dll")>
Private Shared Function AVIFileGetStream(pfile As IntPtr, <Out()> ByRef ppavi As IntPtr, fccType As UInteger, lParam As Integer) As Integer
End Function
<DllImport("avifil32.dll")>
Private Shared Function AVIStreamLength(pavi As IntPtr) As Integer
End Function
<DllImport("avifil32.dll", CharSet:=CharSet.Unicode)>
Private Shared Function AVIStreamInfo(pAVIStream As IntPtr, ByRef psi As _AVISTREAMINFO, lSize As Integer) As Integer
End Function
<DllImport("avifil32.dll")>
Private Shared Function AVIStreamGetFrameOpen(pAVIStream As IntPtr, lpbiWanted As Integer) As IntPtr
End Function
<DllImport("avifil32.dll")>
Private Shared Function AVIStreamGetFrame(pGetFrameObj As IntPtr, lPos As Integer) As IntPtr
End Function
<DllImport("avifil32.dll")>
Private Shared Function AVIStreamGetFrameClose(pGetFrameObj As IntPtr) As Integer
End Function
<DllImport("avifil32.dll")>
Private Shared Function AVIStreamRelease(aviStream As IntPtr) As Integer
End Function
<DllImport("avifil32.dll")>
Private Shared Function AVIFileRelease(pfile As IntPtr) As Integer
End Function
<DllImport("avifil32.dll")>
Private Shared Sub AVIFileExit()
End Sub
<DllImport("winmm.dll")>
Private Shared Function mmioStringToFOURCC(sz As String, uFlags As Integer) As UInteger
End Function
Private Structure BITMAPINFOHEADER
Public biSize As UInt32
Public biWidth As Int32
Public biHeight As Int32
Public biPlanes As Int16
Public biBitCount As Int16
Public biCompression As UInt32
Public biSizeImage As UInt32
Public biXPelsPerMeter As Int32
Public biYPelsPerMeter As Int32
Public biClrUsed As UInt32
Public biClrImportant As UInt32
End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
Private Structure _AVISTREAMINFO
Public fccType As UInt32
Public fccHandler As UInt32
Public dwFlags As UInt32
Public dwCaps As UInt32
Public wPriority As UInt16
Public wLanguage As UInt16
Public dwScale As UInt32
Public dwRate As UInt32
Public dwStart As UInt32
Public dwLength As UInt32
Public dwInitialFrames As UInt32
Public dwSuggestedBufferSize As UInt32
Public dwQuality As UInt32
Public dwSampleSize As UInt32
Public rcFrame As Native.RECT
Public dwEditCount As UInt32
Public dwFormatChangeCount As UInt32
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=64)>
Public szName As String
End Structure
#Region "IDisposable Support"
Private WasDisposed As Boolean
Protected Overridable Sub Dispose(disposing As Boolean)
If Not WasDisposed Then
If FrameObject <> IntPtr.Zero Then AVIStreamGetFrameClose(FrameObject)
If AviStream <> IntPtr.Zero Then AVIStreamRelease(AviStream)
If AviFile <> IntPtr.Zero Then AVIFileRelease(AviFile)
AVIFileExit()
WasDisposed = True
End If
End Sub
Protected Overrides Sub Finalize()
Dispose(False)
MyBase.Finalize()
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class