-
Notifications
You must be signed in to change notification settings - Fork 0
/
MediaInfo.vb
416 lines (328 loc) · 15.4 KB
/
MediaInfo.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
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Text.RegularExpressions
Imports Microsoft.Win32
Public Class MediaInfo
Implements IDisposable
Private Handle As IntPtr
Private Shared Loaded As Boolean
Sub New(path As String)
If Not Loaded Then
Loaded = True
Native.LoadLibrary(Package.MediaInfo.DirPath)
End If
Handle = MediaInfo_New()
MediaInfo_Open(Handle, path)
If Registry.CurrentUser.GetBoolean("Software\" + Forms.Application.ProductName, "DevMode") Then MediaInfo_Option(Handle, "Language", "raw")
End Sub
Private VideoStreamsValue As List(Of VideoStream)
ReadOnly Property VideoStreams() As List(Of VideoStream)
Get
If VideoStreamsValue Is Nothing Then
VideoStreamsValue = New List(Of VideoStream)
Dim count = MediaInfo_Count_Get(Handle, MediaInfoStreamKind.Video, -1)
If count > 0 Then
For index = 0 To count - 1
Dim at As New VideoStream
at.Index = index
Dim streamOrder = GetVideo(index, "StreamOrder")
If Not streamOrder.IsInt Then streamOrder = (index + 1).ToString
at.StreamOrder = streamOrder.ToInt
at.Format = GetVideo(index, "Format")
at.ID = GetVideo(index, "ID").ToInt
VideoStreamsValue.Add(at)
Next
End If
End If
Return VideoStreamsValue
End Get
End Property
ReadOnly Property AudioStreams() As List(Of AudioStream)
Get
Dim ret As New List(Of AudioStream)
Dim count = MediaInfo_Count_Get(Handle, MediaInfoStreamKind.Audio, -1)
Dim offset As Integer
If count > 0 Then
For index = 0 To count - 1
Dim at As New AudioStream
at.Index = index
Dim streamOrder = GetAudio(index, "StreamOrder")
If Not streamOrder.IsInt Then streamOrder = (index + 1).ToString
at.StreamOrder = streamOrder.ToInt + offset
Dim id = GetAudio(index, "ID")
If Not id.IsInt Then id = (index + 2).ToString
at.ID = id.ToInt + offset
at.Codec = GetAudio(index, "Codec")
If at.Codec = "TrueHD / AC3" Then offset += 1
at.Lossy = GetAudio(index, "Compression_Mode") = "Lossy"
at.SamplingRate = GetAudio(index, "SamplingRate").ToInt
at.BitDepth = GetAudio(index, "BitDepth").ToInt
at.CodecString = GetAudio(index, "Codec/String")
at.Format = GetAudio(index, "Format")
at.FormatProfile = GetAudio(index, "Format_Profile")
at.Title = GetAudio(index, "Title").Trim
at.Forced = GetAudio(index, "Forced") = "Yes"
at.Default = GetAudio(index, "Default") = "Yes"
If at.Title.ContainsAny({"IsoMedia", "GPAC", "PID ", "Surround ", "Stereo", "3/2+1", "2/0"}) Then
at.Title = ""
End If
If Not FilePath.IsValidFileSystemName(at.Title) Then
at.Title = FilePath.RemoveIllegalCharsFromName(at.Title)
End If
Dim lm = GetAudio(index, "Language_More")
If lm <> "" Then
If at.Title = "" Then
at.Title = lm
Else
at.Title += " - " + lm
End If
End If
Dim bitrate = GetAudio(index, "BitRate")
If bitrate.IsInt Then
at.Bitrate = CInt(bitrate.ToInt / 1000)
ElseIf bitrate.Contains("/") Then
Dim values = bitrate.Split("/"c)
at.Bitrate = CInt(values(0).ToInt / 1000)
at.Bitrate2 = CInt(values(1).ToInt / 1000)
End If
If at.Bitrate = 0 Then at.Bitrate = GetAudio(index, "FromStats_BitRate").ToInt
at.Delay = GetAudio(index, "Video_Delay").ToInt
If at.Delay = 0 Then at.Delay = GetAudio(index, "Source_Delay").ToInt
Dim channels = GetAudio(index, "Channel(s)")
at.Channels = channels.ToInt
If at.Channels = 0 Then at.Channels = GetAudio(index, "Channel(s)_Original").ToInt
If at.Channels = 0 Then
If channels.Contains("/") Then
Dim values = channels.Split("/"c)
at.Channels = values(0).ToInt
at.Channels2 = values(1).ToInt
End If
End If
at.Language = New Language(GetAudio(index, "Language/String2"))
ret.Add(at)
Next
End If
Return ret
End Get
End Property
Shared Function GetAudioStreams(path As String) As List(Of AudioStream)
Return GetMediaInfo(path).AudioStreams
End Function
Shared Function GetVideoStreams(path As String) As List(Of VideoStream)
Return GetMediaInfo(path).VideoStreams
End Function
Shared Function GetSummary(path As String) As String
Dim mi = GetMediaInfo(path)
MediaInfo_Option(mi.Handle, "Complete", "0")
Dim ret = Marshal.PtrToStringUni(MediaInfo_Inform(mi.Handle, 0))
If ret.Contains("UniqueID/String") Then ret = Regex.Replace(ret, "UniqueID/String +: .+\n", "")
If ret.Contains("Unique ID") Then ret = Regex.Replace(ret, "Unique ID +: .+\n", "")
If ret.Contains("Encoded_Library_Settings") Then ret = Regex.Replace(ret, "Encoded_Library_Settings +: .+\n", "")
If ret.Contains("Encoding settings") Then ret = Regex.Replace(ret, "Encoding settings +: .+\n", "")
If ret.Contains("Format settings, ") Then ret = ret.Replace("Format settings, ", "Format, ")
Return ret.FormatColumn(":").Trim
End Function
Shared Function GetCompleteSummary(path As String) As String
Dim mi = GetMediaInfo(path)
MediaInfo_Option(mi.Handle, "Complete", "1")
Return Marshal.PtrToStringUni(MediaInfo_Inform(mi.Handle, 0))
End Function
Function GetInfo(streamKind As MediaInfoStreamKind, parameter As String) As String
Return Marshal.PtrToStringUni(MediaInfo_Get(Handle, streamKind, 0, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name))
End Function
Function GetAudio(streamNumber As Integer, parameter As String) As String
Return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Audio, streamNumber, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name))
End Function
Function GetText(streamNumber As Integer, parameter As String) As String
Return Marshal.PtrToStringUni(MediaInfo_Get(Handle, MediaInfoStreamKind.Text, streamNumber, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name))
End Function
Function GetInfo(streamKind As MediaInfoStreamKind, streamNumber As Integer, parameter As String) As String
Return Marshal.PtrToStringUni(MediaInfo_Get(Handle, streamKind, streamNumber, parameter, MediaInfoInfoKind.Text, MediaInfoInfoKind.Name))
End Function
Shared Function GetInfo(path As String, streamKind As MediaInfoStreamKind, parameter As String) As String
If path = "" Then Return ""
Return GetMediaInfo(path).GetInfo(streamKind, parameter)
End Function
Shared Function GetMenu(path As String, parameter As String) As String
Return GetInfo(path, MediaInfoStreamKind.Menu, parameter)
End Function
Shared Function GetAudio(path As String, parameter As String) As String
Return GetInfo(path, MediaInfoStreamKind.Audio, parameter)
End Function
Function GetVideo(parameter As String) As String
Return GetInfo(MediaInfoStreamKind.Video, parameter)
End Function
Function GetVideo(streamNumber As Integer, parameter As String) As String
Return GetInfo(MediaInfoStreamKind.Video, streamNumber, parameter)
End Function
Shared Function GetVideo(path As String, parameter As String) As String
Return GetInfo(path, MediaInfoStreamKind.Video, parameter)
End Function
Function GetGeneral(parameter As String) As String
Return GetInfo(MediaInfoStreamKind.General, parameter)
End Function
Shared Function GetGeneral(path As String, parameter As String) As String
Return GetInfo(path, MediaInfoStreamKind.General, parameter)
End Function
Function GetFrameRate(Optional defaultValue As Double = 25) As Double
Dim num = GetVideo("FrameRate_Num").ToInt
Dim den = GetVideo("FrameRate_Den").ToInt
If num > 0 AndAlso den > 0 Then Return num / den
Dim ret = GetVideo("FrameRate")
If ret = "" Then ret = GetVideo("FrameRate_Original")
If ret = "" Then ret = GetVideo("FrameRate_Nominal")
If ret.IsDouble Then Return ret.ToDouble Else Return defaultValue
End Function
Shared Function GetFrameRate(path As String, Optional defaultValue As Double = 25) As Double
Return GetMediaInfo(path).GetFrameRate(defaultValue)
End Function
Function GetChannels() As Integer
Dim channelsString = GetInfo(MediaInfoStreamKind.Audio, "Channel(s)")
Dim ret = channelsString.ToInt
If ret = 0 Then ret = GetInfo(MediaInfoStreamKind.Audio, "Channel(s)_Original").ToInt
If ret = 0 Then
If channelsString.Contains("/") Then
Dim values = channelsString.Split("/"c)
Dim value0 = values(0).ToInt
Dim value1 = values(1).ToInt
If value0 >= value1 Then ret = value0 Else ret = value1
End If
End If
If ret = 0 Then ret = 2
Return ret
End Function
Shared Function GetChannels(path As String) As Integer
Return GetMediaInfo(path).GetChannels
End Function
Shared Function GetAudioCodecs(path As String) As String
Dim ret = GetGeneral(path, "Audio_Codec_List")
If ret.Contains("MPEG-1 Audio layer 2") Then ret = ret.Replace("MPEG-1 Audio layer 2", "MP2")
If ret.Contains("MPEG-1 Audio layer 3") Then ret = ret.Replace("MPEG-1 Audio layer 3", "MP3")
If ret.Contains("MPEG-2 Audio layer 3") Then ret = ret.Replace("MPEG-2 Audio layer 3", "MP3")
Return ret
End Function
Shared Function GetVideoCodec(path As String) As String
Dim ret = MediaInfo.GetVideo(path, "Codec/String")
Select Case ret
Case "MPEG-4 Visual"
ret = "MPEG-4V"
Case "MPEG-1 Video"
ret = "MPEG-1"
Case "V_MPEGH/ISO/HEVC"
ret = "HEVC"
Case "MPEG-2 Video"
ret = "MPEG-2"
Case "V_VP8"
ret = "VP8"
Case "V_VP9"
ret = "VP9"
Case "0x00000000"
ret = MediaInfo.GetVideo(path, "Format")
End Select
Return ret
End Function
Function GetVideoCount() As Integer
Return MediaInfo_Count_Get(Handle, MediaInfoStreamKind.Video, -1)
End Function
Shared Function GetVideoCount(Path As String) As Integer
Return GetMediaInfo(Path).GetVideoCount
End Function
Function GetAudioCount() As Integer
Return MediaInfo_Count_Get(Handle, MediaInfoStreamKind.Audio, -1)
End Function
Shared Function GetAudioCount(path As String) As Integer
Return GetMediaInfo(path).GetAudioCount
End Function
Function GetSubtitleCount() As Integer
Return MediaInfo_Count_Get(Handle, MediaInfoStreamKind.Text, -1)
End Function
Shared Function GetSubtitleCount(path As String) As Integer
Return GetMediaInfo(path).GetSubtitleCount
End Function
Shared Cache As New Dictionary(Of String, MediaInfo)
Shared Function GetMediaInfo(path As String) As MediaInfo
If path = "" Then Return Nothing
Dim key = path & File.GetLastWriteTime(path).Ticks
If Cache.ContainsKey(key) Then Return Cache(key)
Dim ret As New MediaInfo(path)
Cache(key) = ret
Return ret
End Function
Shared Sub ClearCache()
For Each i In Cache
i.Value.Dispose()
Next
Cache.Clear()
End Sub
#Region "IDisposable"
Private Disposed As Boolean
Sub Dispose() Implements IDisposable.Dispose
If Not Disposed Then
Disposed = True
MediaInfo_Close(Handle)
MediaInfo_Delete(Handle)
End If
End Sub
Protected Overrides Sub Finalize()
Dispose()
End Sub
#End Region
#Region "native"
<DllImport("MediaInfo.dll")>
Private Shared Function MediaInfo_New() As IntPtr
End Function
<DllImport("MediaInfo.dll")>
Private Shared Sub MediaInfo_Delete(Handle As IntPtr)
End Sub
<DllImport("MediaInfo.dll", CharSet:=CharSet.Unicode)>
Private Shared Function MediaInfo_Open(Handle As IntPtr, FileName As String) As Integer
End Function
<DllImport("MediaInfo.dll")>
Private Shared Function MediaInfo_Close(Handle As IntPtr) As Integer
End Function
<DllImport("MediaInfo.dll")>
Private Shared Function MediaInfo_Inform(Handle As IntPtr,
Reserved As Integer) As IntPtr
End Function
<DllImport("MediaInfo.dll", CharSet:=CharSet.Unicode)>
Private Shared Function MediaInfo_Get(Handle As IntPtr,
StreamKind As MediaInfoStreamKind,
StreamNumber As Integer, Parameter As String,
KindOfInfo As MediaInfoInfoKind,
KindOfSearch As MediaInfoInfoKind) As IntPtr
End Function
<DllImport("MediaInfo.dll", CharSet:=CharSet.Unicode)>
Private Shared Function MediaInfo_Option(Handle As IntPtr,
OptionString As String,
Value As String) As IntPtr
End Function
<DllImport("MediaInfo.dll")>
Private Shared Function MediaInfo_State_Get(Handle As IntPtr) As Integer
End Function
<DllImport("MediaInfo.dll")>
Private Shared Function MediaInfo_Count_Get(Handle As IntPtr,
StreamKind As MediaInfoStreamKind,
StreamNumber As Integer) As Integer
End Function
#End Region
End Class
Public Enum MediaInfoStreamKind
General
Video
Audio
Text
Other
Image
Menu
Max
End Enum
Public Enum MediaInfoInfoKind
Name
Text
Measure
Options
NameText
MeasureText
Info
HowTo
End Enum