diff --git a/Changelog.md b/Changelog.md index 98e49413..12082c61 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,4 +1,10 @@ +### + +- new: %dpi% macro added, returnes the DPI value of the main dialog screen +- new: High DPI aware Info AviSynth filter profile added to misc section: Info(size=16*%dpi%/96) +- new: the VFW/avifile interface was replaced with a wrapper library + ### 2.0.6.2 - new: crop dialog supports hardware accelerated video rendering diff --git a/Encoding/VideoEncoder.vb b/Encoding/VideoEncoder.vb index d2c38427..4654d7a3 100644 --- a/Encoding/VideoEncoder.vb +++ b/Encoding/VideoEncoder.vb @@ -671,7 +671,7 @@ Public Class BatchEncoder End Using Dim bits = (New FileInfo(p.TempDir + p.TargetFile.Base + "_CompCheck." + OutputExt).Length) * 8 - p.Compressibility = (bits / script.GetFrames) / (p.TargetWidth * p.TargetHeight) + p.Compressibility = (bits / script.GetFrameCount) / (p.TargetWidth * p.TargetHeight) OnAfterCompCheck() diff --git a/Encoding/ffmpegEnc.vb b/Encoding/ffmpegEnc.vb index 6338352b..d9186c9e 100644 --- a/Encoding/ffmpegEnc.vb +++ b/Encoding/ffmpegEnc.vb @@ -105,7 +105,7 @@ Public Class ffmpegEnc proc.WorkingDirectory = p.TempDir proc.Package = Package.ffmpeg proc.Arguments = args - If args.Contains(p.Script.Path) Then proc.Frames = p.Script.GetFrames + If args.Contains(p.Script.Path) Then proc.Frames = p.Script.GetFrameCount proc.Start() End Using End Sub diff --git a/Encoding/x264Enc.vb b/Encoding/x264Enc.vb index ae06f5fa..7ab776b1 100644 --- a/Encoding/x264Enc.vb +++ b/Encoding/x264Enc.vb @@ -115,7 +115,7 @@ Public Class x264Enc End Try Dim bits = (New FileInfo(p.TempDir + p.TargetFile.Base + "_CompCheck." + OutputExt).Length) * 8 - p.Compressibility = (bits / script.GetFrames) / (p.TargetWidth * p.TargetHeight) + p.Compressibility = (bits / script.GetFrameCount) / (p.TargetWidth * p.TargetHeight) OnAfterCompCheck() g.MainForm.Assistant() @@ -963,7 +963,7 @@ Public Class x264Params If includePaths Then Dim input = If(PipingTool.ValueText = "none", script.Path.Escape, "-") - If input = "-" Then args += " --demuxer y4m --frames " & script.GetFrames + If input = "-" Then args += " --demuxer y4m --frames " & script.GetFrameCount If Mode.Value = x264RateMode.TwoPass OrElse Mode.Value = x264RateMode.ThreePass Then args += " --stats " + (p.TempDir + p.TargetFile.Base + ".stats").Escape diff --git a/Encoding/x265Enc.vb b/Encoding/x265Enc.vb index 30c3fbea..f75220ff 100644 --- a/Encoding/x265Enc.vb +++ b/Encoding/x265Enc.vb @@ -112,7 +112,7 @@ Public Class x265Enc End Try Dim bits = (New FileInfo(p.TempDir + p.TargetFile.Base + "_CompCheck." + OutputExt).Length) * 8 - p.Compressibility = (bits / script.GetFrames) / (p.TargetWidth * p.TargetHeight) + p.Compressibility = (bits / script.GetFrameCount) / (p.TargetWidth * p.TargetHeight) OnAfterCompCheck() g.MainForm.Assistant() @@ -1107,7 +1107,7 @@ Public Class x265Params If includePaths Then If PipingTool.ValueText <> "none" Then If Frames.Value = 0 AndAlso Not IsCustom(pass, "--frames") Then - sb.Append(" --frames " & script.GetFrames) + sb.Append(" --frames " & script.GetFrameCount) End If sb.Append(" --y4m") diff --git a/Forms/CodeEditor.vb b/Forms/CodeEditor.vb index 30642509..d865e81d 100644 --- a/Forms/CodeEditor.vb +++ b/Forms/CodeEditor.vb @@ -89,10 +89,8 @@ Public Class CodeEditor script.Path = p.TempDir + p.TargetFile.Base + "_play." + script.FileType script.Filters = GetFilters() - Dim errMsg = script.GetErrorMessage - - If Not errMsg Is Nothing Then - MsgError(errMsg) + If script.GetError <> "" Then + MsgError(script.GetError) Exit Sub End If @@ -105,10 +103,8 @@ Public Class CodeEditor script.Path = p.TempDir + p.TargetFile.Base + "_play." + script.FileType script.Filters = GetFilters() - Dim errMsg = script.GetErrorMessage - - If Not errMsg Is Nothing Then - MsgError(errMsg) + If script.GetError <> "" Then + MsgError(script.GetError) Exit Sub End If @@ -125,10 +121,8 @@ Public Class CodeEditor script.Path = p.TempDir + p.TargetFile.Base + "_editor." + script.FileType script.Filters = GetFilters() - Dim errMsg = script.GetErrorMessage - - If Not errMsg Is Nothing Then - MsgError(errMsg) + If script.GetError <> "" Then + MsgError(script.GetError) Exit Sub End If @@ -147,10 +141,8 @@ Public Class CodeEditor script.Path = p.TempDir + p.TargetFile.Base + "_editor." + script.FileType script.Filters = GetFilters() - Dim errMsg = script.GetErrorMessage - - If Not errMsg Is Nothing Then - MsgError(errMsg) + If script.GetError <> "" Then + MsgError(script.GetError) Exit Sub End If diff --git a/Forms/CropForm.vb b/Forms/CropForm.vb index 314f627a..4a8fd25b 100644 --- a/Forms/CropForm.vb +++ b/Forms/CropForm.vb @@ -27,6 +27,7 @@ Public Class CropForm Friend WithEvents StatusStrip As System.Windows.Forms.StatusStrip Friend WithEvents tsbMenu As System.Windows.Forms.ToolStripDropDownButton Friend WithEvents laStatus As System.Windows.Forms.ToolStripStatusLabel + Private Sub InitializeComponent() Me.pLeftActive = New System.Windows.Forms.Panel() Me.pTopActive = New System.Windows.Forms.Panel() @@ -147,18 +148,17 @@ Public Class CropForm #End Region - Private AVI As AVIFile + Private FrameServer As FrameServer + Private Renderer As VideoRenderer Private SelectedBorderColor As Color = ToolStripRendererEx.ColorBorder Private Side As AnchorStyles Private ActiveCropSide As AnchorStyles Private CommandManager As New CommandManager Private WithEvents CustomMenu As CustomMenu - Private Renderer As VideoRenderer Sub New() MyBase.New() InitializeComponent() - UpdateStyles() MinimumSize = New Size(CInt(Font.Size * 90), CInt(Font.Size * 70)) @@ -213,26 +213,10 @@ Public Class CropForm pTopActive.BackColor = SelectedBorderColor Side = AnchorStyles.Top - - Dim script As New VideoScript - script.Engine = p.Script.Engine - script.Path = p.TempDir + p.TargetFile.Base + "_crop." + script.FileType - script.Filters.Add(p.Script.GetFilter("Source").GetCopy) - script.Synchronize(True, True, True) - - AVI = New AVIFile(script.Path) - Renderer = New VideoRenderer(pVideo, AVI) - - If s.LastPosition < (AVI.FrameCount - 1) Then - AVI.Position = s.LastPosition - End If - - tbPosition.Value = AVI.Position - UpdateAll() End Sub Private Sub TrackLength_Scroll() Handles tbPosition.Scroll - AVI.Position = tbPosition.Value + Renderer.Position = tbPosition.Value Renderer.Draw() End Sub @@ -427,15 +411,15 @@ Public Class CropForm End Sub Private Sub pVideo_Paint(sender As Object, e As PaintEventArgs) Handles pVideo.Paint - Renderer.Draw() + Renderer?.Draw() End Sub Private Sub CropForm_SizeChanged() Handles MyBase.SizeChanged - If Not Renderer Is Nothing Then Renderer.Draw() + Renderer?.Draw() End Sub Private Sub CropForm_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing - Dim err = p.Script.GetErrorMessage + Dim err = p.Script.GetError If err <> "" Then Using td As New TaskDialog(Of String) @@ -452,9 +436,9 @@ Public Class CropForm End If p.RemindToCrop = False - s.LastPosition = AVI.Position + s.LastPosition = Renderer.Position Renderer.Dispose() - AVI.Dispose() + FrameServer.Dispose() End Sub Private Sub tbPosition_Enter() Handles tbPosition.Enter @@ -463,7 +447,7 @@ Public Class CropForm Private Sub SetDialogSize(w As Integer, h As Integer) ClientSize = New Size(ClientSize.Width + w - pVideo.Width, ClientSize.Height + h - pVideo.Height) - Renderer.Draw() + Renderer?.Draw() End Sub Protected Overrides Function IsInputKey(keyData As Keys) As Boolean @@ -580,8 +564,8 @@ Public Class CropForm offset As Integer) - AVI.Position += offset - tbPosition.Value = AVI.Position + Renderer.Position += offset + tbPosition.Value = Renderer.Position Renderer.Draw() End Sub @@ -603,6 +587,26 @@ Public Class CropForm ShowHelpDialog() End Sub + Protected Overrides Sub OnLoad(e As EventArgs) + MyBase.OnLoad(e) + + Dim script As New VideoScript + script.Engine = p.Script.Engine + script.Path = p.TempDir + p.TargetFile.Base + "_crop." + script.FileType + script.Filters.Add(p.Script.GetFilter("Source").GetCopy) + script.Synchronize(True, True, True) + + FrameServer = New FrameServer(script.Path) + Renderer = New VideoRenderer(pVideo, FrameServer) + + If s.LastPosition < (FrameServer.Info.FrameCount - 1) Then + Renderer.Position = s.LastPosition + End If + + tbPosition.Value = Renderer.Position + UpdateAll() + End Sub + Private Sub tsbMenu_Click(sender As Object, e As EventArgs) Handles tsbMenu.Click ContextMenuStrip.Show(MousePosition) End Sub diff --git a/Forms/MainForm.vb b/Forms/MainForm.vb index dbb6db44..83cad8df 100644 --- a/Forms/MainForm.vb +++ b/Forms/MainForm.vb @@ -1843,7 +1843,9 @@ Public Class MainForm preferredSourceFilter.Script) End If - If Not g.VerifyRequirements() Then Throw New AbortException + If Not g.VerifyRequirements() Then + Throw New AbortException + End If p.LastOriginalSourceFile = p.SourceFile p.FirstOriginalSourceFile = p.SourceFile @@ -2030,7 +2032,7 @@ Public Class MainForm Try p.SourceScript.Synchronize() - errorMsg = p.SourceScript.GetErrorMessage + errorMsg = p.SourceScript.GetError Catch ex As Exception errorMsg = ex.Message End Try @@ -2077,7 +2079,7 @@ Public Class MainForm Try p.SourceScript.Synchronize() - errorMsg = p.SourceScript.GetErrorMessage + errorMsg = p.SourceScript.GetError Catch ex As Exception errorMsg = ex.Message End Try @@ -2891,16 +2893,16 @@ Public Class MainForm End If If Not (MouseButtons = MouseButtons.Left AndAlso ActiveControl Is tbResize) Then - If Not p.Script.GetErrorMessage Is Nothing AndAlso Not g.VerifyRequirements Then - If ProcessTip(p.Script.GetErrorMessage) Then + If p.Script.GetError <> "" AndAlso Not g.VerifyRequirements Then + If ProcessTip(p.Script.GetError) Then CanIgnoreTip = False gbAssistant.Text = "Script Error" Return False End If End If - If Not p.Script.GetErrorMessage Is Nothing Then - If ProcessTip(p.Script.GetErrorMessage) Then + If p.Script.GetError <> "" Then + If ProcessTip(p.Script.GetError) Then CanIgnoreTip = False gbAssistant.Text = "Script Error" Return False @@ -3681,10 +3683,8 @@ Public Class MainForm Exit Sub End If - Dim errMsg = p.Script.GetErrorMessage - - If Not errMsg Is Nothing Then - MsgError("Script Error", errMsg) + If p.Script.GetError <> "" Then + MsgError("Script Error", p.Script.GetError) Exit Sub End If @@ -5392,11 +5392,11 @@ Public Class MainForm Sub UpdateSourceParameters() If Not p.SourceScript Is Nothing Then Try - p.SourceWidth = p.SourceScript.GetSize.Width - p.SourceHeight = p.SourceScript.GetSize.Height - p.SourceSeconds = CInt(p.SourceScript.GetFrames / p.SourceScript.GetFramerate) + p.SourceWidth = p.SourceScript.GetInfo.Width + p.SourceHeight = p.SourceScript.GetInfo.Height + p.SourceSeconds = CInt(p.SourceScript.GetFrameCount / p.SourceScript.GetFramerate) p.SourceFrameRate = p.SourceScript.GetFramerate - p.SourceFrames = p.SourceScript.GetFrames + p.SourceFrames = p.SourceScript.GetFrameCount Catch ex As Exception MsgError("Source filter returned invalid parameters", p.SourceScript.GetFullScript) Throw New AbortException() @@ -5910,10 +5910,10 @@ Public Class MainForm fd.Multiselect = True If fd.ShowDialog = DialogResult.OK Then - Using f As New SimpleSettingsForm("Thumbnail Options") - f.ScaleClientSize(27, 20) + Using form As New SimpleSettingsForm("Thumbnail Options") + form.ScaleClientSize(27, 20) - Dim ui = f.SimpleUI + Dim ui = form.SimpleUI Dim page = ui.CreateFlowPage("main page") ui.Store = s page.SuspendLayout() @@ -5923,10 +5923,12 @@ Public Class MainForm Dim mode = ui.AddMenu(Of Integer) mode.Text = "Row Count Mode" + mode.Expandet = True mode.Add("Manual", 0) mode.Add("Row count is calculated based on time interval", 1) mode.Button.Value = s.Storage.GetInt("Thumbnail Mode") mode.Button.SaveAction = Sub(value) s.Storage.SetInt("Thumbnail Mode", value) + AddHandler mode.Button.ValueChangedUser, Sub() row.Visible = mode.Button.Value = 0 interval.Visible = mode.Button.Value = 1 @@ -5979,6 +5981,12 @@ Public Class MainForm row.Visible = mode.Button.Value = 0 interval.Visible = mode.Button.Value = 1 + Dim margin = ui.AddNum() + margin.Text = "Margin:" + margin.Config = {0, 100} + margin.NumEdit.Value = s.Storage.GetInt("Thumbnail Margin", 5) + margin.NumEdit.SaveAction = Sub(value) s.Storage.SetInt("Thumbnail Margin", CInt(value)) + Dim cq = ui.AddNum() cq.Text = "Compression Quality:" cq.Config = {1, 100} @@ -5987,7 +5995,7 @@ Public Class MainForm AddHandler k.Button.ValueChangedUser, Sub() cq.Visible = k.Button.Value = "jpg" Dim logo = ui.AddBool() - logo.Text = "Disable Logo" + logo.Text = "Disable StaxRip Logo" logo.Help = "Enable or disable the StaxRip Watermark" logo.Checked = s.Storage.GetBool("Logo", False) logo.SaveAction = Sub(value) s.Storage.SetBool("Logo", CBool(value)) @@ -5997,18 +6005,19 @@ Public Class MainForm output.Checked = s.Storage.GetBool("StaxRipOutput", False) output.SaveAction = Sub(value) s.Storage.SetBool("StaxRipOutput", value) - Dim customDirectory = ui.AddTextMenu() 'Custom Output Directory - customDirectory.Expandet = True - customDirectory.Label.Visible = False - customDirectory.Edit.Text = s.Storage.GetString("StaxRipDirectory", p.DefaultTargetFolder) - customDirectory.Edit.SaveAction = Sub(value) s.Storage.SetString("StaxRipDirectory", value) - customDirectory.AddMenu("Browse Folder...", Function() g.BrowseFolder(p.DefaultTargetFolder)) + Dim customDir = ui.AddTextButton() + customDir.Visible = output.Checked + customDir.Expandet = True + customDir.Label.Visible = False + customDir.Edit.Text = s.Storage.GetString("StaxRipDirectory", p.DefaultTargetFolder) + customDir.Edit.SaveAction = Sub(value) s.Storage.SetString("StaxRipDirectory", value) + customDir.BrowseFolder() - AddHandler output.CheckStateChanged, Sub() customDirectory.Visible = output.Checked = True + AddHandler output.CheckStateChanged, Sub() customDir.Visible = output.Checked = True page.ResumeLayout() - If f.ShowDialog() = DialogResult.OK Then + If form.ShowDialog() = DialogResult.OK Then ui.Save() For Each i In fd.FileNames diff --git a/Forms/PreviewForm.vb b/Forms/PreviewForm.vb index 9448e2fa..8e93c27f 100644 --- a/Forms/PreviewForm.vb +++ b/Forms/PreviewForm.vb @@ -277,15 +277,14 @@ Public Class PreviewForm #End Region - Public AVI As AVIFile - Public RangeStart As Integer = -1 - + Private FrameServer As FrameServer + Private Renderer As VideoRenderer + Private RangeStart As Integer = -1 Private PreviewScript As VideoScript Private SizeFactor As Double = 1 Private TargetFrames As Integer Private WithEvents GenericMenu As CustomMenu Private CommandManager As New CommandManager - Private Renderer As VideoRenderer Private Const TrackBarBorder As Integer = 1 Private Const TrackBarGap As Integer = 1 @@ -315,15 +314,19 @@ Public Class PreviewForm End Sub Sub RefreshScript() - TargetFrames = p.Script.GetFrames + TargetFrames = p.Script.GetFrameCount - If Not AVI Is Nothing Then - AVI.Dispose() + If Not Renderer Is Nothing Then + Renderer.Dispose() + End If + + If Not FrameServer Is Nothing Then + FrameServer.Dispose() End If PreviewScript.Synchronize(True, True, True) - AVI = New AVIFile(PreviewScript.Path) - Renderer = New VideoRenderer(pVideo, AVI) + FrameServer = New FrameServer(PreviewScript.Path) + Renderer = New VideoRenderer(pVideo, FrameServer) Renderer.ShowInfo = s.ShowPreviewInfo Dim workingArea = Screen.FromControl(Me).WorkingArea @@ -347,7 +350,10 @@ Public Class PreviewForm NormalScreen() End If - If s.LastPosition < AVI.FrameCount - 1 Then AVI.Position = s.LastPosition + If s.LastPosition < FrameServer.Info.FrameCount - 1 Then + Renderer.Position = s.LastPosition + End If + AfterPositionChanged() ShowButtons(Not s.HidePreviewButtons) Refresh() @@ -366,7 +372,7 @@ Public Class PreviewForm If Calc.IsARSignalingRequired Then ratio = Calc.GetTargetDAR Else - ratio = AVI.FrameSize.Width / AVI.FrameSize.Height + ratio = FrameServer.Info.Width / FrameServer.Info.Height End If Dim b = Screen.FromControl(Me).Bounds @@ -404,12 +410,12 @@ Public Class PreviewForm Function GetNormalSize() As Size Dim ret As Size - Dim frameHeight = AVI.FrameSize.Height + Dim frameHeight = FrameServer.Info.Height If Calc.IsARSignalingRequired Then ret = New Size(CInt(frameHeight * SizeFactor * Calc.GetTargetDAR), CInt(frameHeight * SizeFactor)) Else - ret = New Size(CInt(AVI.FrameSize.Width * SizeFactor), CInt(frameHeight * SizeFactor)) + ret = New Size(CInt(FrameServer.Info.Width * SizeFactor), CInt(frameHeight * SizeFactor)) End If Return ret @@ -533,9 +539,9 @@ Public Class PreviewForm End If Using rangeSetPen As New Pen(Color.DarkOrange, trackHeight) - If RangeStart > -1 AndAlso RangeStart <= AVI.Position Then + If RangeStart > -1 AndAlso RangeStart <= Renderer.Position Then g.DrawLine(rangeSetPen, GetDrawPos(RangeStart) - CInt(TrackBarPosition / 2), - pnTrack.Height \ 2, GetDrawPos(AVI.Position) + + pnTrack.Height \ 2, GetDrawPos(Renderer.Position) + CInt(TrackBarPosition / 2), pnTrack.Height \ 2) End If End Using @@ -550,7 +556,7 @@ Public Class PreviewForm posPen.Alignment = Drawing2D.PenAlignment.Center - Dim pos = GetDrawPos(AVI.Position) + Dim pos = GetDrawPos(Renderer.Position) g.DrawLine(posPen, pos - CInt(TrackBarPosition / 2), @@ -604,19 +610,19 @@ Public Class PreviewForm Description("Frames to jump, negative values jump backward.")> pos As Integer) - SetPos(AVI.Position + pos) + SetPos(Renderer.Position + pos) End Sub Sub SetPos(pos As Integer) - AVI.Position = pos + Renderer.Position = pos Renderer.Draw() AfterPositionChanged() End Sub Private Sub AfterPositionChanged() - s.LastPosition = AVI.Position + s.LastPosition = Renderer.Position DrawTrack() - Dim time = TimeSpan.FromSeconds(AVI.Position / AVI.FrameRate).ToString.Shorten(12) + Dim time = TimeSpan.FromSeconds(Renderer.Position / FrameServer.FrameRate).ToString.Shorten(12) If time.StartsWith("00") Then time = time.Substring(3) Text = "Preview " & s.LastPosition & " " + time End Sub @@ -624,12 +630,12 @@ Public Class PreviewForm Sub GoToTime() Dim d As Date - d = d.AddSeconds(AVI.Position / AVI.FrameRate) + d = d.AddSeconds(Renderer.Position / FrameServer.FrameRate) Dim value = InputBox.Show("Time:", "Go To Time", d.ToString("HH:mm:ss.fff")) If value <> "" Then Try - AVI.Position = CInt((TimeSpan.Parse(value).TotalMilliseconds / 1000) * AVI.FrameRate) + Renderer.Position = CInt((TimeSpan.Parse(value).TotalMilliseconds / 1000) * FrameServer.FrameRate) Renderer.Draw() AfterPositionChanged() Catch @@ -639,11 +645,11 @@ Public Class PreviewForm Sub GoToFrame() - Dim value = InputBox.Show("Frame:", "Go To Frame", AVI.Position.ToString) + Dim value = InputBox.Show("Frame:", "Go To Frame", Renderer.Position.ToString) Dim pos As Integer If Integer.TryParse(value, pos) Then - AVI.Position = pos + Renderer.Position = pos Renderer.Draw() AfterPositionChanged() End If @@ -669,10 +675,10 @@ Public Class PreviewForm Sub SetRangeStart() Dim r = GetCurrentRange() - If r Is Nothing OrElse AVI.Position = r.End Then - RangeStart = AVI.Position + If r Is Nothing OrElse Renderer.Position = r.End Then + RangeStart = Renderer.Position Else - r.Start = AVI.Position + r.Start = Renderer.Position End If MergeRanges() @@ -682,14 +688,14 @@ Public Class PreviewForm Sub SetRangeEnd() If RangeStart > -1 Then - p.Ranges.Add(New Range(RangeStart, AVI.Position)) + p.Ranges.Add(New Range(RangeStart, Renderer.Position)) p.Ranges.Sort() RangeStart = -1 Else Dim r = GetCurrentRange() If Not r Is Nothing Then - r.End = AVI.Position + r.End = Renderer.Position RangeStart = -1 End If End If @@ -720,13 +726,13 @@ Public Class PreviewForm Sub SplitRange() If p.Ranges.Count = 0 Then - p.Ranges.Add(New Range(0, AVI.FrameCount - 1)) + p.Ranges.Add(New Range(0, FrameServer.Info.FrameCount - 1)) End If For Each i In p.Ranges.ToArray - If i.Start < AVI.Position AndAlso i.End > AVI.Position Then - p.Ranges.Add(New Range(i.Start, AVI.Position)) - p.Ranges.Add(New Range(AVI.Position + 1, i.End)) + If i.Start < Renderer.Position AndAlso i.End > Renderer.Position Then + p.Ranges.Add(New Range(i.Start, Renderer.Position)) + p.Ranges.Add(New Range(Renderer.Position + 1, i.End)) p.Ranges.Remove(i) Exit For End If @@ -746,7 +752,7 @@ Public Class PreviewForm Sub DeleteRange() For Each i As Range In p.Ranges.ToArray - If AVI.Position >= i.Start AndAlso AVI.Position <= i.End Then + If Renderer.Position >= i.Start AndAlso Renderer.Position <= i.End Then p.Ranges.Remove(i) End If Next @@ -839,14 +845,14 @@ Public Class PreviewForm list.Add(i.End) Next - list.Add(AVI.Position - 1) + list.Add(Renderer.Position - 1) list.Sort() - Dim index = list.IndexOf(AVI.Position - 1) - 1 + Dim index = list.IndexOf(Renderer.Position - 1) - 1 If index >= 0 AndAlso index < list.Count Then - AVI.Position = CInt(list(index)) + Renderer.Position = CInt(list(index)) Renderer.Draw() AfterPositionChanged() End If @@ -855,7 +861,7 @@ Public Class PreviewForm Sub CopyTime() Dim d As Date - d = d.AddSeconds(AVI.Position / AVI.FrameRate) + d = d.AddSeconds(Renderer.Position / FrameServer.FrameRate) Clipboard.SetText(d.ToString("HH:mm:ss.fff")) End Sub @@ -868,13 +874,13 @@ Public Class PreviewForm list.Add(i.End) Next - list.Add(AVI.Position + 1) + list.Add(Renderer.Position + 1) list.Sort() - Dim index = list.IndexOf(AVI.Position + 1) + 1 + Dim index = list.IndexOf(Renderer.Position + 1) + 1 If index >= 0 AndAlso index < list.Count Then - AVI.Position = CInt(list(index)) + Renderer.Position = CInt(list(index)) Renderer.Draw() AfterPositionChanged() End If @@ -884,10 +890,10 @@ Public Class PreviewForm Sub SaveBitmap() Using d As New SaveFileDialog d.SetFilter({"bmp"}) - d.FileName = p.TargetFile.Base + " - " & AVI.Position + d.FileName = p.TargetFile.Base + " - " & Renderer.Position If d.ShowDialog = DialogResult.OK Then - AVI.GetBitmap.Save(d.FileName, Imaging.ImageFormat.Bmp) + BitmapUtil.CreateBitmap(FrameServer, Renderer.Position).Save(d.FileName, ImageFormat.Bmp) End If End Using End Sub @@ -896,10 +902,10 @@ Public Class PreviewForm Sub SavePng() Using d As New SaveFileDialog d.SetFilter({"png"}) - d.FileName = p.TargetFile.Base + " - " & AVI.Position + d.FileName = p.TargetFile.Base + " - " & Renderer.Position If d.ShowDialog = DialogResult.OK Then - AVI.GetBitmap.Save(d.FileName, Imaging.ImageFormat.Png) + BitmapUtil.CreateBitmap(FrameServer, Renderer.Position).Save(d.FileName, ImageFormat.Png) End If End Using End Sub @@ -917,7 +923,7 @@ Public Class PreviewForm Dim params = New EncoderParameters(1) params.Param(0) = New EncoderParameter(Encoder.Quality, q.ToInt) Dim info = ImageCodecInfo.GetImageEncoders.Where(Function(arg) arg.FormatID = ImageFormat.Jpeg.Guid).First - AVI.GetBitmap.Save(path, info, params) + BitmapUtil.CreateBitmap(FrameServer, Renderer.Position).Save(path, info, params) End If End Sub @@ -925,7 +931,7 @@ Public Class PreviewForm Sub SaveJPG() Using d As New SaveFileDialog d.DefaultExt = "jpg" - d.FileName = p.TargetFile.Base + " - " & AVI.Position + d.FileName = p.TargetFile.Base + " - " & Renderer.Position If d.ShowDialog = DialogResult.OK Then SaveJpgByPath(d.FileName) End Using @@ -950,7 +956,7 @@ Public Class PreviewForm Next If td.Show() <> "" Then - AVI.Position = CInt((TimeSpan.Parse(td.SelectedValue).TotalMilliseconds / 1000) * AVI.FrameRate) + Renderer.Position = CInt((TimeSpan.Parse(td.SelectedValue).TotalMilliseconds / 1000) * FrameServer.FrameRate) Renderer.Draw() AfterPositionChanged() End If @@ -1043,12 +1049,12 @@ Public Class PreviewForm MyBase.OnFormClosing(e) Instances.Remove(Me) UpdateTrim(p.Script) - s.LastPosition = AVI.Position - p.CutFrameCount = AVI.FrameCount - p.CutFrameRate = AVI.FrameRate + s.LastPosition = Renderer.Position + p.CutFrameCount = FrameServer.Info.FrameCount + p.CutFrameRate = FrameServer.FrameRate g.MainForm.UpdateFilters() Renderer.Dispose() - AVI.Dispose() + FrameServer.Dispose() End Sub Sub UpdateTrim(script As VideoScript) @@ -1096,7 +1102,7 @@ Public Class PreviewForm Function GetCurrentRange() As Range For Each i In p.Ranges - If AVI.Position >= i.Start AndAlso AVI.Position <= i.End Then + If Renderer.Position >= i.Start AndAlso Renderer.Position <= i.End Then Return i End If Next diff --git a/Forms/TestForm.Designer.vb b/Forms/TestForm.Designer.vb index 255940b3..9307a278 100644 --- a/Forms/TestForm.Designer.vb +++ b/Forms/TestForm.Designer.vb @@ -22,48 +22,19 @@ Partial Class TestForm 'Do not modify it using the code editor. Private Sub InitializeComponent() - Me.TrackBar1 = New System.Windows.Forms.TrackBar() - Me.Panel1 = New System.Windows.Forms.Panel() - CType(Me.TrackBar1, System.ComponentModel.ISupportInitialize).BeginInit() Me.SuspendLayout() ' - 'TrackBar1 - ' - Me.TrackBar1.Anchor = CType(((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left) _ - Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) - Me.TrackBar1.Location = New System.Drawing.Point(26, 1034) - Me.TrackBar1.Name = "TrackBar1" - Me.TrackBar1.Size = New System.Drawing.Size(1647, 136) - Me.TrackBar1.TabIndex = 0 - ' - 'Panel1 - ' - Me.Panel1.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _ - Or System.Windows.Forms.AnchorStyles.Left) _ - Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles) - Me.Panel1.Location = New System.Drawing.Point(53, 45) - Me.Panel1.Name = "Panel1" - Me.Panel1.Size = New System.Drawing.Size(1586, 935) - Me.Panel1.TabIndex = 1 - ' 'TestForm ' Me.AutoScaleDimensions = New System.Drawing.SizeF(288.0!, 288.0!) Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi Me.ClientSize = New System.Drawing.Size(1685, 1182) - Me.Controls.Add(Me.Panel1) - Me.Controls.Add(Me.TrackBar1) Me.Font = New System.Drawing.Font("Segoe UI", 9.0!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte)) Me.Name = "TestForm" Me.ShowIcon = False Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent Me.Text = "Test" - CType(Me.TrackBar1, System.ComponentModel.ISupportInitialize).EndInit() Me.ResumeLayout(False) - Me.PerformLayout() End Sub - - Friend WithEvents TrackBar1 As TrackBar - Friend WithEvents Panel1 As Panel End Class diff --git a/Forms/TestForm.vb b/Forms/TestForm.vb index 588e7f27..7098a44d 100644 --- a/Forms/TestForm.vb +++ b/Forms/TestForm.vb @@ -1,18 +1,7 @@  Public Class TestForm - Private Server As FrameServer - Private Renderer As VideoRenderer2 - Sub New() InitializeComponent() - 'Server = New FrameServer("D:\Samples\Jill_temp\Jill_new_preview.avs") - Server = New FrameServer("D:\Samples\Jill_temp\Jill_new_preview.vpy") - - If Server.Error <> "" Then - MsgError(Server.Error) - End If - - TrackBar1.Maximum = Server.Info.FrameCount - 1 End Sub Shared Sub ShowForm() @@ -20,21 +9,4 @@ Public Class TestForm form.ShowDialog() End Using End Sub - - Private Sub TrackBar1_Scroll(sender As Object, e As EventArgs) Handles TrackBar1.Scroll - Server.Position = TrackBar1.Value - Renderer.Draw() - End Sub - - Private Sub TestForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load - Renderer = New VideoRenderer2(Panel1, Server) - End Sub - - Private Sub Panel1_Paint(sender As Object, e As PaintEventArgs) Handles Panel1.Paint - Renderer.Draw() - End Sub - - Private Sub TestForm_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed - Server.Dispose() - End Sub End Class diff --git a/Forms/VideoComparisonForm.vb b/Forms/VideoComparisonForm.vb index c68e7e22..24ee60a3 100644 --- a/Forms/VideoComparisonForm.vb +++ b/Forms/VideoComparisonForm.vb @@ -73,7 +73,6 @@ Public Class VideoComparisonForm Private Sub Save() For Each i As VideoTab In TabControl.TabPages - i.AVI.Position = Pos Dim outputPath = i.SourceFile.Dir & Pos & " " + i.SourceFile.Base + ".png" Using b = i.GetBitmap @@ -149,12 +148,6 @@ Public Class VideoComparisonForm End If End Sub - Private Sub TabControl_Deselecting(sender As Object, e As TabControlCancelEventArgs) Handles TabControl.Deselecting - For Each i As VideoTab In TabControl.TabPages - i.AVI.Position = Pos - Next - End Sub - Private Sub CodecComparisonForm_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed Dispose() End Sub @@ -218,12 +211,12 @@ Public Class VideoComparisonForm Private Sub GoToTime() Dim tab = DirectCast(TabControl.SelectedTab, VideoTab) Dim d As Date - d = d.AddSeconds(tab.AVI.Position / tab.AVI.FrameRate) + d = d.AddSeconds(Pos / tab.Server.FrameRate) Dim value = InputBox.Show("Time:", "Go To Time", d.ToString("HH:mm:ss.fff")) Dim time As TimeSpan If value <> "" AndAlso TimeSpan.TryParse(value, time) Then - TrackBar.Value = CInt((time.TotalMilliseconds / 1000) * tab.AVI.FrameRate) + TrackBar.Value = CInt((time.TotalMilliseconds / 1000) * tab.Server.FrameRate) End If End Sub @@ -234,7 +227,7 @@ Public Class VideoComparisonForm Public Class VideoTab Inherits TabPage - Property AVI As AVIFile + Property Server As FrameServer Property Form As VideoComparisonForm Property SourceFile As String @@ -245,7 +238,7 @@ Public Class VideoComparisonForm End Sub Sub Reload() - AVI.Dispose() + Server.Dispose() Open(SourceFile) End Sub @@ -285,15 +278,15 @@ Public Class VideoComparisonForm End If avs.Synchronize(True) - AVI = New AVIFile(avs.Path) + Server = New FrameServer(avs.Path) Try FileHelp.Delete(sourePath + ".ffindex") Catch ex As Exception End Try - If Form.TrackBar.Maximum < AVI.FrameCount - 1 Then - Form.TrackBar.Maximum = AVI.FrameCount - 1 + If Form.TrackBar.Maximum < Server.Info.FrameCount - 1 Then + Form.TrackBar.Maximum = Server.Info.FrameCount - 1 End If Dim csvFile = sourePath.DirAndBase + ".csv" @@ -327,7 +320,7 @@ Public Class VideoComparisonForm Sub Draw() Dim padding As Padding - Dim sizeToFit = New Size(AVI.FrameSize.Width, AVI.FrameSize.Height) + Dim sizeToFit = New Size(Server.Info.Width, Server.Info.Height) Dim rect As New Rectangle( padding.Left, padding.Top, @@ -363,7 +356,8 @@ Public Class VideoComparisonForm End Sub Function GetBitmap() As Bitmap - Dim ret = AVI.GetBitmap + Dim ret = BitmapUtil.CreateBitmap(Server, Pos) + ret.RotateFlip(RotateFlipType.RotateNoneFlipY) Using g = Graphics.FromImage(ret) g.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias @@ -385,7 +379,7 @@ Public Class VideoComparisonForm End Function Sub TrackBarValueChanged() - AVI.Position = Form.TrackBar.Value + Pos = Form.TrackBar.Value Try Draw() @@ -403,8 +397,8 @@ Public Class VideoComparisonForm Form.lInfo.Text = FrameInfo(Form.TrackBar.Value) Else Dim d As Date - d = d.AddSeconds(AVI.Position / AVI.FrameRate) - Form.lInfo.Text = "Position: " & AVI.Position & ", Time: " + d.ToString("HH:mm:ss.fff") + ", Size: " & AVI.FrameSize.Width & " x " & AVI.FrameSize.Height + d = d.AddSeconds(Pos / Server.FrameRate) + Form.lInfo.Text = "Position: " & Pos & ", Time: " + d.ToString("HH:mm:ss.fff") + ", Size: " & Server.Info.Width & " x " & Server.Info.Height End If Form.lInfo.Refresh() @@ -416,8 +410,8 @@ Public Class VideoComparisonForm End Sub Protected Overrides Sub Dispose(disposing As Boolean) - If Not AVI Is Nothing Then - AVI.Dispose() + If Not Server Is Nothing Then + Server.Dispose() End If MyBase.Dispose(disposing) diff --git a/FrameServer/AviSynthServer.cpp b/FrameServer/AviSynthServer.cpp index 088d1663..7494fd4d 100644 --- a/FrameServer/AviSynthServer.cpp +++ b/FrameServer/AviSynthServer.cpp @@ -48,21 +48,24 @@ HRESULT __stdcall AviSynthServer::OpenFile(WCHAR* file) static HMODULE dll = LoadLibrary(L"AviSynth"); + if (!dll) + dll = LoadLibrary(L"AviSynth"); + if (!dll) throw std::exception("AviSynth+ installation cannot be found"); - IScriptEnvironment* (*CreateScriptEnvironment)(int version) = - (IScriptEnvironment * (*)(int)) GetProcAddress(dll, "CreateScriptEnvironment"); + IScriptEnvironment2* (*CreateScriptEnvironment2)(int version) = + (IScriptEnvironment2 * (*)(int)) GetProcAddress(dll, "CreateScriptEnvironment2"); - if (!CreateScriptEnvironment) - throw std::exception("Cannot resolve AviSynth+ CreateScriptEnvironment function"); + if (!CreateScriptEnvironment2) + throw std::exception("Cannot resolve AviSynth+ CreateScriptEnvironment2 function"); - m_ScriptEnvironment = CreateScriptEnvironment(6); + m_ScriptEnvironment = CreateScriptEnvironment2(6); if (!m_ScriptEnvironment) throw std::exception("A newer AviSynth+ version is required"); - AVS_linkage = m_ScriptEnvironment->GetAVSLinkage(); + AVS_linkage = m_Linkage = m_ScriptEnvironment->GetAVSLinkage(); std::string ansiFile = ConvertWideToANSI(file); AVSValue arg(ansiFile.c_str()); @@ -74,11 +77,12 @@ HRESULT __stdcall AviSynthServer::OpenFile(WCHAR* file) m_Clip = m_AVSValue.AsClip(); VideoInfo avsInfo = m_Clip->GetVideoInfo(); + m_Info.Width = avsInfo.width; m_Info.Height = avsInfo.height; m_Info.FrameCount = avsInfo.num_frames; - m_Info.FrameRateNumerator = avsInfo.fps_numerator; - m_Info.FrameRateDenominator = avsInfo.fps_denominator; + m_Info.FrameRateNum = avsInfo.fps_numerator; + m_Info.FrameRateDen = avsInfo.fps_denominator; return S_OK; } @@ -102,16 +106,18 @@ HRESULT __stdcall AviSynthServer::OpenFile(WCHAR* file) void* __stdcall AviSynthServer::GetFrame(int position) { - if (!m_ScriptEnvironment) + if (m_Info.FrameCount == 0) return NULL; + AVS_linkage = m_Linkage; + try { m_Frame = m_Clip->GetFrame(position, m_ScriptEnvironment); auto readPtr = m_Frame->GetReadPtr(); - + if (!readPtr) - throw std::exception("AviSynth+ frame pointer is null"); + throw std::exception("AviSynth+ pixel data pointer is null"); return (void*)readPtr; } @@ -119,10 +125,14 @@ void* __stdcall AviSynthServer::GetFrame(int position) { m_Error = ConvertAnsiToWide(e.msg); } - catch (std::exception & e) + catch (std::exception& e) { m_Error = ConvertAnsiToWide(e.what()); } + catch (...) + { + m_Error = L"Exception: AviSynthServer::GetFrame"; + } return NULL; } @@ -150,16 +160,20 @@ AviSynthServer::~AviSynthServer() void AviSynthServer::Free() { + AVS_linkage = m_Linkage; + m_Frame = NULL; m_Clip = NULL; m_AVSValue = NULL; - AVS_linkage = NULL; if (m_ScriptEnvironment) { m_ScriptEnvironment->DeleteScriptEnvironment(); m_ScriptEnvironment = NULL; } + + AVS_linkage = NULL; + m_Linkage = NULL; } diff --git a/FrameServer/AviSynthServer.h b/FrameServer/AviSynthServer.h index 9ea63eae..0530151d 100644 --- a/FrameServer/AviSynthServer.h +++ b/FrameServer/AviSynthServer.h @@ -1,12 +1,11 @@ #pragma once -#include - #include "Common.h" #include "FrameServer.h" #include "avisynth_headers\avisynth.h" +#include const AVS_Linkage* AVS_linkage = NULL; @@ -16,16 +15,17 @@ class AviSynthServer : IFrameServer private: - std::atomic m_References = 0; - std::wstring m_Error; - ServerInfo m_Info = {}; + std::atomic m_References = 0; + std::wstring m_Error; + ServerInfo m_Info = {}; - IScriptEnvironment* m_ScriptEnvironment = NULL; - PClip m_Clip; - AVSValue m_AVSValue; - PVideoFrame m_Frame; + IScriptEnvironment2* m_ScriptEnvironment = NULL; + PClip m_Clip; + AVSValue m_AVSValue; + PVideoFrame m_Frame; + const AVS_Linkage* m_Linkage = NULL; - void Free(); + void Free(); public: diff --git a/FrameServer/FrameServer.h b/FrameServer/FrameServer.h index 6fa9f6b5..d1c345eb 100644 --- a/FrameServer/FrameServer.h +++ b/FrameServer/FrameServer.h @@ -12,8 +12,8 @@ struct ServerInfo { int Width; int Height; - int FrameRateNumerator; - int FrameRateDenominator; + int FrameRateNum; + int FrameRateDen; int FrameCount; }; diff --git a/FrameServer/VapourSynthServer.cpp b/FrameServer/VapourSynthServer.cpp index 945f1dee..5c068802 100644 --- a/FrameServer/VapourSynthServer.cpp +++ b/FrameServer/VapourSynthServer.cpp @@ -62,6 +62,9 @@ HRESULT __stdcall VapourSynthServer::OpenFile(WCHAR* file) static HMODULE dll = LoadLibrary(dllPath); + if (!dll) + dll = LoadLibrary(dllPath); + if (!dll) throw std::exception("Failed to load VapourSynth library"); @@ -85,10 +88,8 @@ HRESULT __stdcall VapourSynthServer::OpenFile(WCHAR* file) }; for (auto& i : resolvePairs) - { - if (nullptr == (*(i.first) = GetProcAddress(dll, i.second))) + if (NULL == (*(i.first) = GetProcAddress(dll, i.second))) throw std::exception("Failed to resolve VapourSynth vsscript functions"); - } } wasResolved = true; @@ -114,13 +115,13 @@ HRESULT __stdcall VapourSynthServer::OpenFile(WCHAR* file) m_vsInfo = m_vsAPI->getVideoInfo(m_vsNode); if (!m_vsInfo) - throw std::exception("Failed to get VapourSynth video info"); + throw std::exception("Failed to get VapourSynth info"); m_Info.Width = m_vsInfo->width; m_Info.Height = m_vsInfo->height; m_Info.FrameCount = m_vsInfo->numFrames; - m_Info.FrameRateNumerator = m_vsInfo->fpsNum; - m_Info.FrameRateDenominator = m_vsInfo->fpsDen; + m_Info.FrameRateNum = m_vsInfo->fpsNum; + m_Info.FrameRateDen = m_vsInfo->fpsDen; return S_OK; } @@ -150,7 +151,10 @@ void* __stdcall VapourSynthServer::GetFrame(int position) auto readPtr = m_vsAPI->getReadPtr(frame, 0); if (!readPtr) + { + m_Error = L"VapourSynthServer m_vsAPI->getReadPtr returned NULL"; return NULL; + } if (m_vsFrame) m_vsAPI->freeFrame(m_vsFrame); diff --git a/General/AVIFile.vb b/General/AVIFile.vb deleted file mode 100644 index 958efa9a..00000000 --- a/General/AVIFile.vb +++ /dev/null @@ -1,288 +0,0 @@ - -Imports System.Runtime.InteropServices -Imports System.Reflection - -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 - g.WriteDebugLog("opening avifile: " + path) - 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) - End If - - 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 VirtualDub2 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 + Package.AviSynth.SetupFilename + BR) - ElseIf Sourcefile.Ext = "vpy" Then - Throw New Exception(message + BR2 + "Failed to open VapourSynth script:" + BR2 + Sourcefile + BR2 + "You can try to open the script with VirtualDub2 x64, if it don't open it could be a problem with the script or the VapourSynth x64 setup, if StaxRip don't report a script error and the script looks valid then reinstalling VapourSynth x64 might fix the problem.") - 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 FrameRateNumerator() As Integer - Get - Return CInt(StreamInfo.dwRate) - End Get - End Property - - ReadOnly Property FrameRateDenominator() As Integer - Get - Return CInt(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 - 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 - FrameObject = AVIStreamGetFrameOpen(AviStream, 0) - End If - - If FrameObject <> IntPtr.Zero Then - Return AVIStreamGetFrame(FrameObject, Position) - End If - End Function - - Function GetBitmap() As Bitmap - Dim dib = GetDIB() - - If dib <> IntPtr.Zero Then - Return GetBitmapFromDib(dib) - End If - End Function - - Private Function GetBitmapFromDib(pDIB As IntPtr) As Bitmap - Dim pPix As New IntPtr(pDIB.ToInt64 + Marshal.SizeOf(GetType(BITMAPINFOHEADER))) - Dim pBmp = IntPtr.Zero - GdipCreateBitmapFromGdiDib(pDIB, pPix, pBmp) - Dim mi = GetType(Bitmap).GetMethod("FromGDIplus", BindingFlags.Static Or BindingFlags.NonPublic) - Return DirectCast(mi.Invoke(Nothing, {pBmp}), Bitmap) - End Function - - - Private Interface IAvisynthClipInfo - Function GetError(ByRef msg As IntPtr) As Integer - Function GetParity(value As Integer) As Byte - Function IsFieldBased() As Byte - End Interface - - - Private Shared Function GdipCreateBitmapFromGdiDib(bminfo As IntPtr, pixdat As IntPtr, ByRef image As IntPtr) As Integer - End Function - - - Private Shared Sub AVIFileInit() - End Sub - - - Private Shared Function AVIFileOpen(ByRef ppfile As IntPtr, szFile As String, uMode As Integer, pclsidHandler As IntPtr) As Integer - End Function - - - Private Shared Function AVIFileGetStream(pfile As IntPtr, ByRef ppavi As IntPtr, fccType As UInteger, lParam As Integer) As Integer - End Function - - - Private Shared Function AVIStreamLength(pavi As IntPtr) As Integer - End Function - - - Private Shared Function AVIStreamInfo(pAVIStream As IntPtr, ByRef psi As _AVISTREAMINFO, lSize As Integer) As Integer - End Function - - - Private Shared Function AVIStreamGetFrameOpen(pAVIStream As IntPtr, lpbiWanted As Integer) As IntPtr - End Function - - - Private Shared Function AVIStreamGetFrame(pGetFrameObj As IntPtr, lPos As Integer) As IntPtr - End Function - - - Private Shared Function AVIStreamGetFrameClose(pGetFrameObj As IntPtr) As Integer - End Function - - - Private Shared Function AVIStreamRelease(aviStream As IntPtr) As Integer - End Function - - - Private Shared Function AVIFileRelease(pfile As IntPtr) As Integer - End Function - - - Private Shared Sub AVIFileExit() - End Sub - - - Private Shared Function mmioStringToFOURCC(sz As String, uFlags As Integer) As UInteger - End Function - - - 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 - - Public szName As String - End Structure - - Private WasDisposed As Boolean - - Public Sub Dispose() Implements IDisposable.Dispose - If Not WasDisposed Then - If FrameObject <> IntPtr.Zero Then - AVIStreamGetFrameClose(FrameObject) - End If - - If AviStream <> IntPtr.Zero Then - AVIStreamRelease(AviStream) - End If - - If AviFile <> IntPtr.Zero Then - AVIFileRelease(AviFile) - End If - - AVIFileExit() - WasDisposed = True - g.WriteDebugLog("closing avifile") - End If - End Sub -End Class - -Public 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 \ No newline at end of file diff --git a/General/Automation.vb b/General/Automation.vb index 1b8e61e4..08327dfd 100644 --- a/General/Automation.vb +++ b/General/Automation.vb @@ -1,4 +1,5 @@ -Imports System.Management.Automation.Runspaces + +Imports System.Management.Automation.Runspaces Imports StaxRip.UI Public Class Scripting diff --git a/General/Extensions.vb b/General/Extensions.vb index 7e11355c..8d1dbd12 100644 --- a/General/Extensions.vb +++ b/General/Extensions.vb @@ -151,13 +151,18 @@ Module StringExtensions Function FixDir(instance As String) As String - If instance = "" Then Return "" + If instance = "" Then + Return "" + End If While instance.EndsWith(DirPath.Separator + DirPath.Separator) instance = instance.Substring(0, instance.Length - 1) End While - If instance.EndsWith(DirPath.Separator) Then Return instance + If instance.EndsWith(DirPath.Separator) Then + Return instance + End If + Return instance + DirPath.Separator End Function diff --git a/General/FrameServer.vb b/General/FrameServer.vb index 8ddad266..239a7749 100644 --- a/General/FrameServer.vb +++ b/General/FrameServer.vb @@ -5,29 +5,28 @@ Public Class FrameServer Implements IDisposable Property Info As ServerInfo - Property Server As IFrameServer - Property Position As Integer + Property NativeServer As IFrameServer Sub New(path As String) If path.EndsWith(".avs") Then - Server = CreateAviSynthServer() + NativeServer = CreateAviSynthServer() Else - Server = CreateVapourSynthServer() + NativeServer = CreateVapourSynthServer() End If - Server.OpenFile(path) - Info = Marshal.PtrToStructure(Of ServerInfo)(Server.GetInfo()) + NativeServer.OpenFile(path) + Info = Marshal.PtrToStructure(Of ServerInfo)(NativeServer.GetInfo()) End Sub ReadOnly Property [Error] As String Get - Return Marshal.PtrToStringUni(Server.GetError()) + Return Marshal.PtrToStringUni(NativeServer.GetError()) End Get End Property ReadOnly Property FrameRate As Double Get - Return Info.FrameRateNumerator / Info.FrameRateDenominator + Return Info.FrameRateNum / Info.FrameRateDen End Get End Property @@ -40,9 +39,9 @@ Public Class FrameServer End Function Public Sub Dispose() Implements IDisposable.Dispose - If Not Server Is Nothing Then - Marshal.ReleaseComObject(Server) - Server = Nothing + If Not NativeServer Is Nothing Then + Marshal.ReleaseComObject(NativeServer) + NativeServer = Nothing End If End Sub End Class @@ -59,7 +58,7 @@ End Interface Public Structure ServerInfo Public Width As Integer Public Height As Integer - Public FrameRateNumerator As Integer - Public FrameRateDenominator As Integer + Public FrameRateNum As Integer + Public FrameRateDen As Integer Public FrameCount As Integer End Structure diff --git a/General/General.vb b/General/General.vb index d706adea..0b7e989d 100644 --- a/General/General.vb +++ b/General/General.vb @@ -1,3 +1,4 @@ + Imports System.Runtime.Serialization Imports System.ComponentModel Imports System.Runtime.Serialization.Formatters.Binary @@ -14,9 +15,6 @@ Imports VB6 = Microsoft.VisualBasic Imports Microsoft.Win32 Public Class Folder - -#Region "System" - Shared ReadOnly Property Desktop() As String Get Return Environment.GetFolderPath(Environment.SpecialFolder.Desktop).FixDir @@ -89,10 +87,6 @@ Public Class Folder End Get End Property -#End Region - -#Region "StaxRip" - Shared ReadOnly Property Apps As String Get Return Folder.Startup + "Apps\" @@ -237,8 +231,6 @@ Public Class Folder End Get End Property -#End Region - Private Shared Function SHGetFolderPath(hwndOwner As IntPtr, nFolder As Integer, hToken As IntPtr, dwFlags As Integer, lpszPath As StringBuilder) As Integer End Function diff --git a/General/GlobalClass.vb b/General/GlobalClass.vb index 3b31cd40..0ad3c484 100644 --- a/General/GlobalClass.vb +++ b/General/GlobalClass.vb @@ -85,12 +85,12 @@ Public Class GlobalClass Log.WriteHeader("Script Properties") Dim props = - "Source Frame Count: " & p.SourceScript.GetFrames & BR + + "Source Frame Count: " & p.SourceScript.GetFrameCount & BR + "Source Frame Rate: " & p.SourceScript.GetFramerate.ToString("f6", CultureInfo.InvariantCulture) + BR + - "Source Duration: " + TimeSpan.FromSeconds(g.Get0ForInfinityOrNaN(p.SourceScript.GetFrames / p.SourceScript.GetFramerate)).ToString + BR + - "Target Frame Count: " & p.Script.GetFrames & BR + + "Source Duration: " + TimeSpan.FromSeconds(g.Get0ForInfinityOrNaN(p.SourceScript.GetFrameCount / p.SourceScript.GetFramerate)).ToString + BR + + "Target Frame Count: " & p.Script.GetFrameCount & BR + "Target Frame Rate: " & p.Script.GetFramerate.ToString("f6", CultureInfo.InvariantCulture) + BR + - "Target Duration: " + TimeSpan.FromSeconds(g.Get0ForInfinityOrNaN(p.Script.GetFrames / p.Script.GetFramerate)).ToString + "Target Duration: " + TimeSpan.FromSeconds(g.Get0ForInfinityOrNaN(p.Script.GetFrameCount / p.Script.GetFramerate)).ToString Log.WriteLine(props.FormatColumn(":")) @@ -681,13 +681,13 @@ Public Class GlobalClass End Sub Function IsValidSource(Optional warn As Boolean = True) As Boolean - If p.SourceScript.GetFrames = 0 Then + If p.SourceScript.GetFrameCount = 0 Then If warn Then MsgWarn("Failed to load source.") Return False End If - If Not p.SourceScript.GetErrorMessage Is Nothing Then - MsgError(p.SourceScript.GetErrorMessage) + If p.SourceScript.GetError <> "" Then + MsgError(p.SourceScript.GetError) Return False End If @@ -1024,19 +1024,20 @@ Public Class GlobalClass Sub RunAutoCrop() g.WriteDebugLog("AutoCrop start") - p.SourceScript.Synchronize(True) + p.SourceScript.Synchronize(True, True, True) - Using avi As New AVIFile(p.SourceScript.Path) + Using server As New FrameServer(p.SourceScript.Path) Dim segmentCount = 20 - Dim len = avi.FrameCount \ (segmentCount + 1) + Dim len = server.Info.FrameCount \ (segmentCount + 1) Dim crops(segmentCount - 1) As AutoCrop + Dim pos As Integer For x = 1 To segmentCount - avi.Position = len * x + pos = len * x - Using bmp = avi.GetBitmap - crops(x - 1) = AutoCrop.Start(bmp.Clone(New Rectangle(0, 0, bmp.Width, bmp.Height), PixelFormat.Format32bppRgb), avi.Position) + Using bmp = BitmapUtil.CreateBitmap(server, pos) + crops(x - 1) = AutoCrop.Start(bmp.Clone(New Rectangle(0, 0, bmp.Width, bmp.Height), PixelFormat.Format32bppRgb), pos) End Using Next diff --git a/General/GlobalCommands.vb b/General/GlobalCommands.vb index 07dcb31a..18665e92 100644 --- a/General/GlobalCommands.vb +++ b/General/GlobalCommands.vb @@ -638,9 +638,14 @@ Switches Dim version = Assembly.LoadFile(sourceDir + "StaxRip.exe").GetName.Version Dim releaseType = "-stable" - If version.Revision <> 0 Then releaseType = "-beta" - If Not Directory.Exists(sourceDir) Then Throw New Exception("Source directory not found." + BR2 + sourceDir) + If version.Revision <> 0 Then + releaseType = "-beta" + End If + + If Not Directory.Exists(sourceDir) Then + Throw New Exception("Source directory not found." + BR2 + sourceDir) + End If Dim info = FileVersionInfo.GetVersionInfo(sourceDir + "StaxRip.exe") Dim targetDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), @@ -651,25 +656,34 @@ Switches For Each i In Directory.GetDirectories(targetDir + "\Apps\Plugins\VS") Dim cacheDir = i + "\__pycache__" - If Directory.Exists(cacheDir) Then DirectoryHelp.Delete(cacheDir) + + If Directory.Exists(cacheDir) Then + DirectoryHelp.Delete(cacheDir) + End If Next DirectoryHelp.Delete(targetDir + "\.vs") DirectoryHelp.Delete(targetDir + "\Apps\Plugins\VS\Scripts\__pycache__") DirectoryHelp.Delete(targetDir + "\Apps\Audio\qaac\QTfiles64") - FileHelp.Delete(targetDir + "\Debug.log") FileHelp.Delete(targetDir + "\_StaxRip.log") - FileHelp.Delete(targetDir + "\StaxRip.vshost.exe") - FileHelp.Delete(targetDir + "\StaxRip.vshost.sln") - FileHelp.Delete(targetDir + "\StaxRip.vshost.exe.config") - FileHelp.Delete(targetDir + "\StaxRip.vshost.exe.manifest") FileHelp.Delete(targetDir + "\Apps\Audio\eac3to\log.txt") - FileHelp.Delete(targetDir + "\Apps\Support\DGIndex\DGIndex.ini") + FileHelp.Delete(targetDir + "\Apps\Support\AVSMeter\AVSMeter.ini") FileHelp.Delete(targetDir + "\Apps\Support\chapterEditor\chapterEditor.ini") + FileHelp.Delete(targetDir + "\Apps\Support\DGIndex\DGIndex.ini") FileHelp.Delete(targetDir + "\Apps\Support\MKVToolNix\mkvtoolnix.ini") FileHelp.Delete(targetDir + "\Apps\Support\MKVToolNix\mkvtoolnix-gui.ini") - FileHelp.Delete(targetDir + "\Apps\Support\AVSMeter\AVSMeter.ini") + FileHelp.Delete(targetDir + "\Debug.log") + FileHelp.Delete(targetDir + "\FrameServer.exp") + FileHelp.Delete(targetDir + "\FrameServer.exp") + FileHelp.Delete(targetDir + "\FrameServer.exp") + FileHelp.Delete(targetDir + "\FrameServer.ilk") + FileHelp.Delete(targetDir + "\FrameServer.lib") + FileHelp.Delete(targetDir + "\FrameServer.pdb") + FileHelp.Delete(targetDir + "\StaxRip.vshost.exe") + FileHelp.Delete(targetDir + "\StaxRip.vshost.exe.config") + FileHelp.Delete(targetDir + "\StaxRip.vshost.exe.manifest") + FileHelp.Delete(targetDir + "\StaxRip.vshost.sln") For Each i In Directory.GetFiles(targetDir, "*.ini", IO.SearchOption.AllDirectories) Throw New Exception("ini file found:" + BR2 + i) @@ -680,7 +694,10 @@ Switches p.StartInfo.Arguments = $"a -t7z -mx9 ""{targetDir}.7z"" -r ""{targetDir}\*""" p.Start() p.WaitForExit() - If p.ExitCode > 0 Then Throw New Exception($"7zip exit code: {p.ExitCode}") + + If p.ExitCode > 0 Then + Throw New Exception($"7zip exit code: {p.ExitCode}") + End If End Using If releaseType = "-beta" Then @@ -689,7 +706,10 @@ Switches "C:\Users\frank\Dropbox\public\StaxRip\Builds\"} For Each i In outputDirectories - If Not Directory.Exists(i) Then Continue For + If Not Directory.Exists(i) Then + Continue For + End If + FileHelp.Copy(targetDir.TrimEnd("\"c) + ".7z", i + DirPath.GetName(targetDir) + ".7z", Microsoft.VisualBasic.FileIO.UIOption.AllDialogs) Process.Start(i) Next diff --git a/General/Help.vb b/General/Help.vb index 89e3c593..1288f3e6 100644 --- a/General/Help.vb +++ b/General/Help.vb @@ -142,7 +142,9 @@ Public Class FileHelp End Sub Shared Sub Delete(path As String, Optional recycleOption As RecycleOption = RecycleOption.DeletePermanently) - If File.Exists(path) Then FileSystem.DeleteFile(path, UIOption.OnlyErrorDialogs, recycleOption, UICancelOption.DoNothing) + If File.Exists(path) Then + FileSystem.DeleteFile(path, UIOption.OnlyErrorDialogs, recycleOption, UICancelOption.DoNothing) + End If End Sub End Class diff --git a/General/Misc.vb b/General/Misc.vb index c1c93a65..540f3743 100644 --- a/General/Misc.vb +++ b/General/Misc.vb @@ -3,6 +3,7 @@ Imports System.Drawing.Design Imports System.Drawing.Imaging Imports System.Globalization Imports System.Management +Imports System.Reflection Imports System.Runtime.InteropServices Imports System.Text Imports System.Text.RegularExpressions @@ -82,7 +83,7 @@ Public Class Calc Shared Function GetOverheadKBytes() As Double Dim ret As Double - Dim frames = p.Script.GetFrames + Dim frames = p.Script.GetFrameCount If {"avi", "divx"}.Contains(p.VideoEncoder.Muxer.OutputExt) Then ret += frames * 0.024 @@ -896,6 +897,7 @@ Public Class Macro ret.Add(New Macro("crop_width", "Crop Width", GetType(Integer), "Crop width.")) ret.Add(New Macro("delay", "Audio Delay 1", GetType(Integer), "Audio delay of the first audio track.")) ret.Add(New Macro("delay2", "Audio Delay 2", GetType(Integer), "Audio delay of the second audio track.")) + ret.Add(New Macro("dpi", "Main Dialog DPI", GetType(Integer), "DPI value of the main dialog.")) ret.Add(New Macro("encoder_ext", "Encoder File Extension", GetType(String), "File extension of the format the encoder of the active project outputs.")) ret.Add(New Macro("encoder_out_file", "Encoder Output File", GetType(String), "Output file of the video encoder.")) ret.Add(New Macro("muxer_ext", "Muxer Extension", GetType(String), "Output extension of the active muxer.")) @@ -1119,7 +1121,7 @@ Public Class Macro If value.Contains("%target_seconds%") Then value = value.Replace("%target_seconds%", p.TargetSeconds.ToString) If Not value.Contains("%") Then Return value - If value.Contains("%target_frames%") Then value = value.Replace("%target_frames%", p.Script.GetFrames.ToString) + If value.Contains("%target_frames%") Then value = value.Replace("%target_frames%", p.Script.GetFrameCount.ToString) If Not value.Contains("%") Then Return value If value.Contains("%target_framerate%") Then value = value.Replace("%target_framerate%", p.Script.GetFramerate.ToString("f6", CultureInfo.InvariantCulture)) @@ -1266,6 +1268,9 @@ Public Class Macro If value.Contains("%video_encoder%") Then value = value.Replace("%video_encoder%", TryCast(p.VideoEncoder, BasicVideoEncoder)?.CommandLineParams.GetPackage.Name) If Not value.Contains("%") Then Return value + If value.Contains("%dpi%") Then value = value.Replace("%dpi%", g.MainForm.DeviceDpi.ToString()) + If Not value.Contains("%") Then Return value + If value.Contains("%script_file%") Then p.Script.Synchronize() value = value.Replace("%script_file%", p.Script.Path) @@ -2136,6 +2141,17 @@ Public Class BitmapUtil Property Data As Byte() Property BitmapData As BitmapData + Function GetPixel(x As Integer, y As Integer) As Color + Dim pos = y * BitmapData.Stride + x * 4 + Return Color.FromArgb(Data(pos), Data(pos + 1), Data(pos + 2)) + End Function + + Function GetMax(x As Integer, y As Integer) As Integer + Dim col = GetPixel(x, y) + Dim max = Math.Max(col.R, col.G) + Return Math.Max(max, col.B) + End Function + Shared Function Create(bmp As Bitmap) As BitmapUtil Dim util As New BitmapUtil Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height) @@ -2148,16 +2164,19 @@ Public Class BitmapUtil Return util End Function - Function GetPixel(x As Integer, y As Integer) As Color - Dim pos = y * BitmapData.Stride + x * 4 - Return Color.FromArgb(Data(pos), Data(pos + 1), Data(pos + 2)) + Shared Function CreateBitmap(server As FrameServer, position As Integer) As Bitmap + Dim bmp As New Bitmap(server.Info.Width, server.Info.Height, PixelFormat.Format32bppArgb) + Dim rect As Rectangle = New Rectangle(0, 0, bmp.Width, bmp.Height) + Dim data = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat) + Dim len = ((((bmp.Width * 32) + 31) And Not 31) >> 3) * bmp.Height + CopyMemory(data.Scan0, server.NativeServer.GetFrame(position), CUInt(len)) + bmp.UnlockBits(data) + Return bmp End Function - Function GetMax(x As Integer, y As Integer) As Integer - Dim col = GetPixel(x, y) - Dim max = Math.Max(col.R, col.G) - Return Math.Max(max, col.B) - End Function + + Public Shared Sub CopyMemory(destination As IntPtr, source As IntPtr, length As UInteger) + End Sub End Class Public Class AutoCrop diff --git a/General/VideoRenderer.vb b/General/VideoRenderer.vb index a8c4a8ed..e046a766 100644 --- a/General/VideoRenderer.vb +++ b/General/VideoRenderer.vb @@ -15,12 +15,12 @@ Public Class VideoRenderer Private DirectWriteFactory As ComObject(Of IDWriteFactory) Private RenderTarget As ID2D1HwndRenderTarget Private DeviceContext As ID2D1DeviceContext - Private AVIFile As AVIFile + Private Server As FrameServer Private Control As Control - Sub New(ctrl As Control, avi As AVIFile) - AVIFile = avi - Control = ctrl + Sub New(control As Control, server As FrameServer) + Me.Server = server + Me.Control = control Direct2dFactory = D2D1Functions.D2D1CreateFactory( D2D1_FACTORY_TYPE.D2D1_FACTORY_TYPE_SINGLE_THREADED) @@ -28,9 +28,28 @@ Public Class VideoRenderer DirectWriteFactory = DWriteFunctions.DWriteCreateFactory(Of IDWriteFactory)( DWRITE_FACTORY_TYPE.DWRITE_FACTORY_TYPE_SHARED) - AddHandler ctrl.ClientSizeChanged, AddressOf Resize + AddHandler control.ClientSizeChanged, AddressOf Resize End Sub + Private PositionValue As Integer + + Property Position As Integer + Get + Return PositionValue + End Get + Set(value As Integer) + PositionValue = value + + If PositionValue < 0 Then + PositionValue = 0 + End If + + If PositionValue > Server.Info.FrameCount - 1 Then + PositionValue = Server.Info.FrameCount - 1 + End If + End Set + End Property + Sub Resize(sender As Object, e As EventArgs) Dim bitmapSize = New D2D_SIZE_U With { .width = CUInt(Control.ClientSize.Width), @@ -43,9 +62,9 @@ Public Class VideoRenderer CreateGraphicsResources() Try - Dim dib = AVIFile.GetDIB + Dim pixelPtr = Server.NativeServer.GetFrame(Position) - If dib = IntPtr.Zero Then + If pixelPtr = IntPtr.Zero Then Exit Sub End If @@ -56,16 +75,13 @@ Public Class VideoRenderer .right = Control.ClientSize.Width, .bottom = Control.ClientSize.Height} - DrawBitmap(CreateBitmapFromDIB(dib), ScaleRectangle(destinationRectangle)) + DrawBitmap(CreateBitmap(pixelPtr), ScaleRectangle(destinationRectangle)) DrawInfoText() Else Clear(Color.White) - Dim bitmapHeader = Marshal.PtrToStructure(Of BITMAPINFOHEADER)(dib) - Dim bitmapSize = New Size(bitmapHeader.biWidth, bitmapHeader.biHeight) - - Dim scaleX = Control.Width / bitmapSize.Width - Dim scaleY = Control.Height / bitmapSize.Height + Dim scaleX = Control.Width / Server.Info.Width + Dim scaleY = Control.Height / Server.Info.Height Dim left = CropLeft * scaleX Dim right = CropRight * scaleX @@ -81,10 +97,10 @@ Public Class VideoRenderer Dim sourceRectangle As RectangleF sourceRectangle.X = CropLeft sourceRectangle.Y = CropTop - sourceRectangle.Width = bitmapSize.Width - CropLeft - CropRight - sourceRectangle.Height = bitmapSize.Height - CropTop - CropBottom + sourceRectangle.Width = Server.Info.Width - CropLeft - CropRight + sourceRectangle.Height = Server.Info.Height - CropTop - CropBottom - DrawBitmap(CreateBitmapFromDIB(dib), + DrawBitmap(CreateBitmap(pixelPtr), ConvertRectangle(sourceRectangle), ScaleRectangle(ConvertRectangle(destinationRectangle))) End If @@ -101,19 +117,18 @@ Public Class VideoRenderer End If Dim currentDate As Date - currentDate = currentDate.AddSeconds(AVIFile.Position / AVIFile.FrameRate) + currentDate = currentDate.AddSeconds(Position / Server.FrameRate) Dim lengthtDate As Date - lengthtDate = lengthtDate.AddSeconds(AVIFile.FrameCount / AVIFile.FrameRate) + lengthtDate = lengthtDate.AddSeconds(Server.Info.FrameCount / Server.FrameRate) - Dim frameSize = AVIFile.FrameSize Dim dateFormat = If(lengthtDate.Hour = 0, "mm:ss.fff", "HH:mm:ss.fff") Dim text = - "Frame: " & AVIFile.Position & " of " & AVIFile.FrameCount & BR & + "Frame: " & Position & " of " & Server.Info.FrameCount & BR & "Time: " & currentDate.ToString(dateFormat) + " of " + lengthtDate.ToString(dateFormat) + BR + - "Size: " & frameSize.Width & " x " & frameSize.Height & BR + - "Rate: " & AVIFile.FrameRate.ToString.Shorten(9) & " (" & AVIFile.FrameRateNumerator & "/" & AVIFile.FrameRateDenominator & ")" + "Size: " & Server.Info.Width & " x " & Server.Info.Height & BR + + "Rate: " & Server.FrameRate.ToString.Shorten(9) & " (" & Server.Info.FrameRateNum & "/" & Server.Info.FrameRateDen & ")" Dim layout As IDWriteTextLayout Dim format = DirectWriteFactory.CreateTextFormat("Segoe UI", 13) @@ -221,10 +236,8 @@ Public Class VideoRenderer Marshal.ReleaseComObject(bitmap) End Sub - Function CreateBitmapFromDIB(dib As IntPtr) As ID2D1Bitmap - Dim bitmapHeader = Marshal.PtrToStructure(Of BITMAPINFOHEADER)(dib) - Dim pixelData = dib + Marshal.SizeOf(GetType(BITMAPINFOHEADER)) - Dim pitch = CUInt((((bitmapHeader.biWidth * bitmapHeader.biBitCount) + 31) And Not 31) >> 3) + Function CreateBitmap(pixelPtr As IntPtr) As ID2D1Bitmap + Dim pitch = CUInt((((Server.Info.Width * 32) + 31) And Not 31) >> 3) Dim bitmapProperties As D2D1_BITMAP_PROPERTIES bitmapProperties.pixelFormat = New D2D1_PIXEL_FORMAT() With { @@ -235,11 +248,11 @@ Public Class VideoRenderer bitmapProperties.dpiY = 96 Dim bitmapSize = New D2D_SIZE_U With { - .width = CUInt(bitmapHeader.biWidth), - .height = CUInt(bitmapHeader.biHeight)} + .width = CUInt(Server.Info.Width), + .height = CUInt(Server.Info.Height)} Dim bitmap As ID2D1Bitmap - DeviceContext.CreateBitmap(bitmapSize, pixelData, pitch, bitmapProperties, bitmap).ThrowOnError() + DeviceContext.CreateBitmap(bitmapSize, pixelPtr, pitch, bitmapProperties, bitmap).ThrowOnError() Return bitmap End Function @@ -276,4 +289,4 @@ Public Class VideoRenderer DirectWriteFactory.Dispose() RemoveHandler Control.ClientSizeChanged, AddressOf Resize End Sub -End Class \ No newline at end of file +End Class diff --git a/General/VideoRenderer2.vb b/General/VideoRenderer2.vb deleted file mode 100644 index affe755d..00000000 --- a/General/VideoRenderer2.vb +++ /dev/null @@ -1,276 +0,0 @@ - -Imports System.Runtime.InteropServices -Imports DirectN - -Public Class VideoRenderer2 - Implements IDisposable - - Property CropLeft As Integer - Property CropTop As Integer - Property CropRight As Integer - Property CropBottom As Integer - Property ShowInfo As Boolean - - Private Direct2dFactory As ComObject(Of ID2D1Factory) - Private DirectWriteFactory As ComObject(Of IDWriteFactory) - Private RenderTarget As ID2D1HwndRenderTarget - Private DeviceContext As ID2D1DeviceContext - Private Server As FrameServer - Private Control As Control - - Sub New(control As Control, server As FrameServer) - Me.Server = server - Me.Control = control - - Direct2dFactory = D2D1Functions.D2D1CreateFactory( - D2D1_FACTORY_TYPE.D2D1_FACTORY_TYPE_SINGLE_THREADED) - - DirectWriteFactory = DWriteFunctions.DWriteCreateFactory(Of IDWriteFactory)( - DWRITE_FACTORY_TYPE.DWRITE_FACTORY_TYPE_SHARED) - - AddHandler control.ClientSizeChanged, AddressOf Resize - End Sub - - Sub Resize(sender As Object, e As EventArgs) - Dim bitmapSize = New D2D_SIZE_U With { - .width = CUInt(Control.ClientSize.Width), - .height = CUInt(Control.ClientSize.Height)} - - RenderTarget?.Resize(bitmapSize) - End Sub - - Sub Draw() - CreateGraphicsResources() - - Try - Dim pixelPtr = Server.Server.GetFrame(Server.Position) - - If pixelPtr = IntPtr.Zero Then - Exit Sub - End If - - DeviceContext.BeginDraw() - - If CropLeft + CropTop + CropRight + CropBottom = 0 Then - Dim destinationRectangle = New D2D_RECT_F With { - .right = Control.ClientSize.Width, - .bottom = Control.ClientSize.Height} - - DrawBitmap(CreateBitmap(pixelPtr), ScaleRectangle(destinationRectangle)) - DrawInfoText() - Else - Clear(Color.White) - - Dim bitmapHeader = Marshal.PtrToStructure(Of BITMAPINFOHEADER)(pixelPtr) - Dim bitmapSize = New Size(bitmapHeader.biWidth, bitmapHeader.biHeight) - - Dim scaleX = Control.Width / bitmapSize.Width - Dim scaleY = Control.Height / bitmapSize.Height - - Dim left = CropLeft * scaleX - Dim right = CropRight * scaleX - Dim top = CropTop * scaleY - Dim bottom = CropBottom * scaleY - - Dim destinationRectangle As RectangleF - destinationRectangle.X = CSng(left) - destinationRectangle.Y = CSng(CropTop * scaleY) - destinationRectangle.Width = CSng(Control.Width - left - right) - destinationRectangle.Height = CSng(Control.Height - top - bottom) - - Dim sourceRectangle As RectangleF - sourceRectangle.X = CropLeft - sourceRectangle.Y = CropTop - sourceRectangle.Width = bitmapSize.Width - CropLeft - CropRight - sourceRectangle.Height = bitmapSize.Height - CropTop - CropBottom - - DrawBitmap(CreateBitmap(pixelPtr), - ConvertRectangle(sourceRectangle), - ScaleRectangle(ConvertRectangle(destinationRectangle))) - End If - - DeviceContext.EndDraw() - Catch - ReleaseGraphicsResources() - End Try - End Sub - - Sub DrawInfoText() - If Not ShowInfo Then - Exit Sub - End If - - Dim currentDate As Date - currentDate = currentDate.AddSeconds(Server.Position / Server.FrameRate) - - Dim lengthtDate As Date - lengthtDate = lengthtDate.AddSeconds(Server.Info.FrameCount / Server.FrameRate) - - Dim dateFormat = If(lengthtDate.Hour = 0, "mm:ss.fff", "HH:mm:ss.fff") - - Dim text = - "Frame: " & Server.Position & " of " & Server.Info.FrameCount & BR & - "Time: " & currentDate.ToString(dateFormat) + " of " + lengthtDate.ToString(dateFormat) + BR + - "Size: " & Server.Info.Width & " x " & Server.Info.Height & BR + - "Rate: " & Server.FrameRate.ToString.Shorten(9) & " (" & Server.Info.FrameRateNumerator & "/" & Server.Info.FrameRateDenominator & ")" - - Dim layout As IDWriteTextLayout - Dim format = DirectWriteFactory.CreateTextFormat("Segoe UI", 13) - - DirectWriteFactory.Object.CreateTextLayout( - text, - CUInt(text.Length), - format.Object, - Scale(Control.Width), - Scale(Control.Height), - layout) - - Dim backColor As _D3DCOLORVALUE - backColor.a = 0.7 - Dim backBrush = DeviceContext.CreateSolidColorBrush(Of ID2D1SolidColorBrush)(backColor) - Dim metrics As DWRITE_TEXT_METRICS - layout.GetMetrics(metrics) - Dim padding = Scale(Control.Font.Height) / 3 - Dim rect As D2D_RECT_F - rect.left = Scale(Control.Font.Height) / 2 - rect.top = rect.left - rect.right = rect.left + metrics.width + padding * 2 - rect.bottom = rect.top + metrics.height + padding * 2 - DeviceContext.FillRectangle(rect, backBrush.Object) - Dim foreColor As _D3DCOLORVALUE - foreColor.r = 1 - foreColor.g = 1 - foreColor.b = 1 - foreColor.a = 1 - Dim foreBrush = DeviceContext.CreateSolidColorBrush(Of ID2D1SolidColorBrush)(foreColor) - rect.left += padding - rect.top += padding - rect.right += padding - rect.bottom += padding - DeviceContext.DrawText(text, format.Object, rect, foreBrush.Object) - foreBrush.Dispose() - backBrush.Dispose() - Marshal.ReleaseComObject(layout) - format.Dispose() - End Sub - - Sub Clear(color As Color) - Dim value = ConvertColor(color) - Dim ptr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(_D3DCOLORVALUE))) - Marshal.StructureToPtr(Of _D3DCOLORVALUE)(value, ptr, False) - DeviceContext.Clear(ptr) - Marshal.FreeHGlobal(ptr) - End Sub - - Function ConvertColor(color As Color) As _D3DCOLORVALUE - Dim value As _D3DCOLORVALUE - value.r = color.R / 255.0! - value.g = color.G / 255.0! - value.b = color.B / 255.0! - value.a = color.A / 255.0! - Return value - End Function - - Function Scale(value As Double) As Single - Return CSng((value * 96) / Control.DeviceDpi) - End Function - - Function ScaleRectangle(rect As D2D_RECT_F) As D2D_RECT_F - rect.left = Scale(rect.left) - rect.top = Scale(rect.top) - rect.right = Scale(rect.right) - rect.bottom = Scale(rect.bottom) - Return rect - End Function - - Function ConvertRectangle(inputRect As RectangleF) As D2D_RECT_F - Dim outputRect As D2D_RECT_F - outputRect.left = inputRect.Left - outputRect.top = inputRect.Top - outputRect.right = inputRect.Left + inputRect.Width - outputRect.bottom = inputRect.Top + inputRect.Height - Return outputRect - End Function - - Sub DrawBitmap(bitmap As ID2D1Bitmap, destinationRectangle As D2D_RECT_F) - Dim destinationRectanglePtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(D2D_RECT_F))) - Marshal.StructureToPtr(Of D2D_RECT_F)(destinationRectangle, destinationRectanglePtr, False) - - DeviceContext.DrawBitmap(bitmap, destinationRectanglePtr, 1, - D2D1_INTERPOLATION_MODE.D2D1_INTERPOLATION_MODE_HIGH_QUALITY_CUBIC, - IntPtr.Zero, IntPtr.Zero) - - Marshal.FreeHGlobal(destinationRectanglePtr) - Marshal.ReleaseComObject(bitmap) - End Sub - - Sub DrawBitmap(bitmap As ID2D1Bitmap, sourceRectangle As D2D_RECT_F, destinationRectangle As D2D_RECT_F) - Dim sourceRectanglePtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(D2D_RECT_F))) - Marshal.StructureToPtr(Of D2D_RECT_F)(sourceRectangle, sourceRectanglePtr, False) - - Dim destinationRectanglePtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(D2D_RECT_F))) - Marshal.StructureToPtr(Of D2D_RECT_F)(destinationRectangle, destinationRectanglePtr, False) - - DeviceContext.DrawBitmap(bitmap, destinationRectanglePtr, 1, - D2D1_INTERPOLATION_MODE.D2D1_INTERPOLATION_MODE_HIGH_QUALITY_CUBIC, - sourceRectanglePtr, IntPtr.Zero) - - Marshal.FreeHGlobal(sourceRectanglePtr) - Marshal.FreeHGlobal(destinationRectanglePtr) - Marshal.ReleaseComObject(bitmap) - End Sub - - Function CreateBitmap(pixelPtr As IntPtr) As ID2D1Bitmap - Dim pitch = CUInt((((Server.Info.Width * 32) + 31) And Not 31) >> 3) - Dim bitmapProperties As D2D1_BITMAP_PROPERTIES - - bitmapProperties.pixelFormat = New D2D1_PIXEL_FORMAT() With { - .alphaMode = D2D1_ALPHA_MODE.D2D1_ALPHA_MODE_IGNORE, - .format = DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM} - - bitmapProperties.dpiX = 96 - bitmapProperties.dpiY = 96 - - Dim bitmapSize = New D2D_SIZE_U With { - .width = CUInt(Server.Info.Width), - .height = CUInt(Server.Info.Height)} - - Dim bitmap As ID2D1Bitmap - DeviceContext.CreateBitmap(bitmapSize, pixelPtr, pitch, bitmapProperties, bitmap).ThrowOnError() - Return bitmap - End Function - - Sub CreateGraphicsResources() - If RenderTarget Is Nothing Then - Dim hwndRenderTargetProps = New D2D1_HWND_RENDER_TARGET_PROPERTIES With { - .hwnd = Control.Handle, - .pixelSize = New D2D_SIZE_U(Control.ClientSize.Width, Control.ClientSize.Height)} - - Direct2dFactory.Object.CreateHwndRenderTarget( - New D2D1_RENDER_TARGET_PROPERTIES, - hwndRenderTargetProps, - RenderTarget).ThrowOnError() - - DeviceContext = CType(RenderTarget, ID2D1DeviceContext) - End If - End Sub - - Sub ReleaseGraphicsResources() - If Not DeviceContext Is Nothing Then - Marshal.ReleaseComObject(DeviceContext) - DeviceContext = Nothing - End If - - If Not RenderTarget Is Nothing Then - Marshal.ReleaseComObject(RenderTarget) - RenderTarget = Nothing - End If - End Sub - - Public Sub Dispose() Implements IDisposable.Dispose - ReleaseGraphicsResources() - Direct2dFactory.Dispose() - DirectWriteFactory.Dispose() - RemoveHandler Control.ClientSizeChanged, AddressOf Resize - End Sub -End Class diff --git a/General/VideoScript.vb b/General/VideoScript.vb index 60689d84..9833866d 100644 --- a/General/VideoScript.vb +++ b/General/VideoScript.vb @@ -7,12 +7,8 @@ Imports StaxRip Public Class VideoScript Inherits Profile - Private FrameRateNumerator As Integer - Private FrameRateDenominator As Integer - Private Framerate As Double - Private Frames As Integer - Private Size As Size - Private ErrorMessage As String + Private [Error] As String + Private Info As ServerInfo Property Filters As New List(Of VideoFilter) @@ -228,7 +224,7 @@ clipname.set_output() End If End If - If Frames = 240 OrElse code <> LastCode OrElse (comparePath AndAlso Path <> LastPath) Then + If Me.Error <> "" OrElse code <> LastCode OrElse (comparePath AndAlso Path <> LastPath) Then If Directory.Exists(FilePath.GetDir(Path)) Then If Engine = ScriptEngine.VapourSynth Then ModifyScript(code, Engine).WriteFile(Path, Encoding.UTF8) @@ -247,18 +243,9 @@ clipname.set_output() Throw New AbortException End If - Using avi As New AVIFile(Path) - FrameRateNumerator = avi.FrameRateNumerator - FrameRateDenominator = avi.FrameRateDenominator - Framerate = avi.FrameRate - Frames = avi.FrameCount - Size = avi.FrameSize - ErrorMessage = avi.ErrorMessage - - If Double.IsNaN(Framerate) Then - Throw New ErrorAbortException("AviSynth/VapourSynth Error", - "AviSynth/VapourSynth script returned invalid framerate.") - End If + Using server As New FrameServer(Path) + Info = server.Info + Me.Error = server.Error End Using LastCode = code @@ -441,48 +428,37 @@ clipname.set_output() Return clip End Function - Function GetFramerateDenominator() As Integer - Synchronize(False, False) - Return FrameRateDenominator - End Function - - Function GetFramerateNumerator() As Integer - Synchronize(False, False) - Return FrameRateNumerator - End Function - Function GetFramerate() As Double - Synchronize(False, False) - Return Framerate + Dim info = GetInfo() + Return info.FrameRateNum / info.FrameRateDen End Function - Function GetErrorMessage() As String + Function GetInfo() As ServerInfo Synchronize(False, False) - Return ErrorMessage + Return Info + End Function + + Function GetError() As String + Synchronize(False, False) + Return Me.Error End Function Function GetSeconds() As Integer - Dim fr = GetFramerate() + Dim rate = GetFramerate() - If fr = 0 Then - fr = p.SourceFrameRate + If rate = 0 OrElse Double.IsNaN(rate) Then + rate = p.SourceFrameRate End If - If fr = 0 Then - fr = 25 + If rate = 0 OrElse Double.IsNaN(rate) Then + rate = 25 End If - Return CInt(GetFrames() / fr) + Return CInt(GetFrameCount() / rate) End Function - Function GetFrames() As Integer - Synchronize() - Return Frames - End Function - - Function GetSize() As Size - Synchronize() - Return Size + Function GetFrameCount() As Integer + Return GetInfo.FrameCount End Function Shared Function GetDefaults() As List(Of TargetVideoScript) @@ -503,7 +479,7 @@ clipname.set_output() script.Filters.Add(New VideoFilter("Crop", "Crop", "clip = core.std.Crop(clip, %crop_left%, %crop_right%, %crop_top%, %crop_bottom%)", False)) script.Filters.Add(New VideoFilter("Noise", "DFTTest", "clip = core.dfttest.DFTTest(clip, sigma=6, tbsize=3, opt=3)", False)) script.Filters.Add(New VideoFilter("Field", "QTGMC Medium", $"clip = core.std.SetFieldBased(clip, 2) # 1=BFF, 2=TFF{BR}clip = havsfunc.QTGMC(clip, TFF=True, Preset='Medium')", False)) - 'filter is too long + 'code is too long 'script.Filters.Add(New VideoFilter("FrameRate", "SVPFlow", "crop_string = """"" + BR + "resize_string = """"" + BR + "super_params = ""{pel:1,scale:{up:0},gpu:1,full:false,rc:true}""" + BR + "analyse_params = ""{block:{w:16},main:{search:{coarse:{type:4,distance:-6,bad:{sad:2000,range:24}},type:4}},refine:[{thsad:250}]}""" + BR + "smoothfps_params = ""{gpuid:11,linear:true,rate:{num:60000,den:1001,abs:true},algo:23,mask:{area:200},scene:{}}""" + BR + "def interpolate(clip):" + BR + " input = clip" + BR + " if crop_string!='':" + BR + " input = eval(crop_string)" + BR + " if resize_string!='':" + BR + " input = eval(resize_string)" + BR + " super = core.svp1.Super(input,super_params)" + BR + " vectors = core.svp1.Analyse(super[""clip""],super[""data""],input,analyse_params)" + BR + " smooth = core.svp2.SmoothFps(input,super[""clip""],super[""data""],vectors[""clip""],vectors[""data""],smoothfps_params,src=clip)" + BR + " smooth = core.std.AssumeFPS(smooth,fpsnum=smooth.fps_num,fpsden=smooth.fps_den)" + BR + " return smooth" + BR + "clip = interpolate(clip)", False)) script.Filters.Add(New VideoFilter("Color", "Respec", "clip = core.fmtc.resample(clip, css='444')" + BR + "clip = core.fmtc.matrix(clip, mats='709', matd='709')" + BR + "clip = core.fmtc.resample(clip, css='420')" + BR + "clip = core.fmtc.bitdepth(clip, bits=10, fulls=False, fulld=False)", False)) script.Filters.Add(New VideoFilter("Resize", "Spline64Resize", "clip = core.fmtc.resample(clip, kernel='spline64', w=%target_width%, h=%target_height%)", False)) @@ -543,7 +519,10 @@ Public Class TargetVideoScript Overrides Property Path() As String Get - If p.SourceFile = "" OrElse p.TargetFile.Base = "" Then Return "" + If p.SourceFile = "" OrElse p.TargetFile.Base = "" Then + Return "" + End If + Return p.TempDir + p.TargetFile.Base + "." + FileType End Get Set(value As String) @@ -557,7 +536,10 @@ Public Class SourceVideoScript Overrides Property Path() As String Get - If p.SourceFile = "" Then Return "" + If p.SourceFile = "" Then + Return "" + End If + Return p.TempDir + p.TargetFile.Base + "_source." + p.Script.FileType End Get Set(value As String) @@ -748,6 +730,7 @@ Public Class FilterCategory misc.Filters.Add(New VideoFilter(misc.Name, "MTMode | Set Max Memory", "SetMemoryMax($enter_text:Enter the Maximum Memory Avisynth Can use$)")) misc.Filters.Add(New VideoFilter(misc.Name, "Histogram", "Histogram(""levels"", bits=$select:msg:Select BitDepth;8;10;12$)")) misc.Filters.Add(New VideoFilter(misc.Name, "SplitVertical", "Splitvertical=true")) + misc.Filters.Add(New VideoFilter(misc.Name, "Info", "Info(size=16*%dpi%/96)")) ret.Add(misc) Dim resize As New FilterCategory("Resize") diff --git a/StaxRip.vbproj b/StaxRip.vbproj index ff747626..78356095 100644 --- a/StaxRip.vbproj +++ b/StaxRip.vbproj @@ -184,7 +184,6 @@ - True @@ -305,7 +304,6 @@ Code - diff --git a/UI/ImageUtils.vb b/UI/ImageUtils.vb index d12baf36..de9b1ec3 100644 --- a/UI/ImageUtils.vb +++ b/UI/ImageUtils.vb @@ -52,8 +52,13 @@ End Class Public Class Thumbnails Shared Sub SaveThumbnails(inputFile As String, proj As Project) - If Not File.Exists(inputFile) Then Exit Sub - If Not Package.AviSynth.VerifyOK(True) Then Exit Sub + If Not File.Exists(inputFile) Then + Exit Sub + End If + + If Not Package.AviSynth.VerifyOK(True) Then + Exit Sub + End If If proj Is Nothing Then proj = New Project @@ -69,49 +74,50 @@ Public Class Thumbnails Dim rowCount = s.Storage.GetInt("Thumbnail Rows", 6) Dim dar = MediaInfo.GetVideo(inputFile, "DisplayAspectRatio") Dim height = CInt(width / Convert.ToSingle(dar, CultureInfo.InvariantCulture)) - Dim gap = CInt((width * columnCount) * 0.000) + Dim gap = CInt((width * columnCount) * (s.Storage.GetInt("Thumbnail Margin", 5) / 1000)) Dim font = New Font(fontname, (width * columnCount) \ 80, FontStyle.Bold, GraphicsUnit.Pixel) Dim foreColor = Color.Black - width = width - width Mod 4 - height = height - height Mod 4 + width = width - width Mod 16 + height = height - height Mod 16 - Dim avsdoc As New VideoScript - avsdoc.Path = Path.Combine(Folder.Temp + "Thumbnails.avs") + Dim script As New VideoScript + script.Path = Path.Combine(Folder.Temp + "Thumbnails.avs") - If inputFile.EndsWith("mp4") Then - avsdoc.Filters.Add(New VideoFilter("LWLibavVideoSource(""" + inputFile + "" + """, format = ""YUV420P8"").Spline64Resize(" & width & "," & height & ")")) + If inputFile.Ext = "mp4" Then + script.Filters.Add(New VideoFilter($"LSMASHVideoSource(""{inputFile}"")")) Else - avsdoc.Filters.Add(New VideoFilter("FFVideoSource(""" + inputFile + "" + """, colorspace = ""YV12"").Spline64Resize(" & width & "," & height & ")")) + script.Filters.Add(New VideoFilter($"FFVideoSource(""{inputFile}"")")) End If - avsdoc.Filters.Add(New VideoFilter("ConvertToRGB(matrix=""Rec709"")")) + script.Filters.Add(New VideoFilter($"Spline64Resize({width},{height})")) - Dim errorMsg = "" + Dim mode = s.Storage.GetInt("Thumbnail Mode") + Dim intervalSec = s.Storage.GetInt("Thumbnail Interval") - Try - avsdoc.Synchronize() - Dim mode = s.Storage.GetInt("Thumbnail Mode") - Dim intervalSec = s.Storage.GetInt("Thumbnail Interval") - If intervalSec <> 0 AndAlso mode = 1 Then rowCount = CInt((avsdoc.GetSeconds / intervalSec) / columnCount) - errorMsg = p.SourceScript.GetErrorMessage - Catch ex As Exception - errorMsg = ex.Message - End Try + If intervalSec <> 0 AndAlso mode = 1 Then + rowCount = CInt((script.GetSeconds / intervalSec) / columnCount) + End If + + Dim errorMsg = script.GetError If errorMsg <> "" Then MsgError("Failed to open file." + BR2 + inputFile, errorMsg) Exit Sub End If - Dim frames = avsdoc.GetFrames + Dim frames = script.GetFrameCount Dim count = columnCount * rowCount Dim bitmaps As New List(Of Bitmap) - Using avi As New AVIFile(avsdoc.Path) + script.Synchronize(True, True, True) + + Using server As New FrameServer(script.Path) + Dim serverPos As Integer + For x = 1 To count - avi.Position = CInt((frames / count) * x) - CInt((frames / count) / 2) - Dim bitmap = New Bitmap(avi.GetBitmap()) + serverPos = CInt((frames / count) * x) - CInt((frames / count) / 2) + Dim bitmap = BitmapUtil.CreateBitmap(server, serverPos) Using g = Graphics.FromImage(bitmap) g.InterpolationMode = InterpolationMode.HighQualityBicubic @@ -119,34 +125,35 @@ Public Class Thumbnails g.SmoothingMode = SmoothingMode.AntiAlias g.PixelOffsetMode = PixelOffsetMode.HighQuality - Dim dur = TimeSpan.FromSeconds(avi.FrameCount / avi.FrameRate) - Dim timestamp = StaxRip.g.GetTimeString(avi.Position / avi.FrameRate) + Dim dur = TimeSpan.FromSeconds(server.Info.FrameCount / server.FrameRate) + Dim timestamp = StaxRip.g.GetTimeString(serverPos / server.FrameRate) Dim ft As New Font("Segoe UI", font.Size, FontStyle.Bold, GraphicsUnit.Pixel) - Dim gp As New GraphicsPath() - Dim sz = g.MeasureString(timestamp, ft) - Dim pt As Point - Dim pos = s.Storage.GetInt("Thumbnail Position", 1) + Using gp As New GraphicsPath() + Dim sz = g.MeasureString(timestamp, ft) + Dim pt As Point + Dim pos = s.Storage.GetInt("Thumbnail Position", 1) - If pos = 0 OrElse pos = 2 Then - pt.X = ft.Height \ 10 - Else - pt.X = CInt(bitmap.Width - sz.Width - ft.Height / 10) - End If + If pos = 0 OrElse pos = 2 Then + pt.X = ft.Height \ 10 + Else + pt.X = CInt(bitmap.Width - sz.Width - ft.Height / 10) + End If - If pos = 2 OrElse pos = 3 Then - pt.Y = CInt(bitmap.Height - sz.Height) - Else - pt.Y = 0 - End If + If pos = 2 OrElse pos = 3 Then + pt.Y = CInt(bitmap.Height - sz.Height) + Else + pt.Y = 0 + End If - gp.AddString(timestamp, ft.FontFamily, CInt(ft.Style), ft.Size, pt, New StringFormat()) + gp.AddString(timestamp, ft.FontFamily, CInt(ft.Style), ft.Size, pt, New StringFormat()) - Using pen As New Pen(Brushes.Black, ft.Height \ 5) - g.DrawPath(pen, gp) + Using pen As New Pen(Brushes.Black, ft.Height \ 5) + g.DrawPath(pen, gp) + End Using + + g.FillPath(Brushes.Gainsboro, gp) End Using - - g.FillPath(Brushes.Gainsboro, gp) End Using bitmaps.Add(bitmap) @@ -156,19 +163,11 @@ Public Class Thumbnails height = height + gap End Using - Try - FileHelp.Delete(avsdoc.Path) - Catch ex As Exception - End Try - - Try - If inputFile.EndsWith("mp4") Then - FileHelp.Delete(inputFile + ".lwi") - Else - FileHelp.Delete(inputFile + ".ffindex") - End If - Catch ex As Exception - End Try + If inputFile.Ext = "mp4" Then + FileHelp.Delete(inputFile + ".lwi") + Else + FileHelp.Delete(inputFile + ".ffindex") + End If Dim infoSize As String Dim infoWidth = MediaInfo.GetVideo(inputFile, "Width") @@ -176,7 +175,11 @@ Public Class Thumbnails Dim infoLength = New FileInfo(inputFile).Length Dim infoDuration = MediaInfo.GetGeneral(inputFile, "Duration").ToInt Dim audioCodecs = MediaInfo.GetAudioCodecs(inputFile) - If audioCodecs = "" Then audioCodecs = "" + + If audioCodecs = "" Then + audioCodecs = "" + End If + Dim channels = MediaInfo.GetAudio(inputFile, "Channel(s)").ToInt Dim subSampling = MediaInfo.GetVideo(inputFile, "ChromaSubsampling").Replace(":", "") If subSampling = "" Then subSampling = "" @@ -219,6 +222,7 @@ Public Class Thumbnails g.SmoothingMode = SmoothingMode.AntiAlias g.PixelOffsetMode = PixelOffsetMode.HighQuality g.Clear(s.ThumbnailBackgroundColor) + Dim rect = New RectangleF(gap, 0, imageWidth - gap * 2, captionHeight) Dim format As New StringFormat format.LineAlignment = StringAlignment.Center diff --git a/UI/Misc.vb b/UI/Misc.vb index 28ac8c30..25686e7b 100644 --- a/UI/Misc.vb +++ b/UI/Misc.vb @@ -66,11 +66,17 @@ Namespace UI End If MyBase.OnLoad(e) - If Not DesignHelp.IsDesignMode Then s.WindowPositions?.RestorePosition(Me) + + If Not DesignHelp.IsDesignMode Then + s.WindowPositions?.RestorePosition(Me) + End If End Sub Protected Overrides Sub OnFormClosing(e As FormClosingEventArgs) - If Not s.WindowPositions Is Nothing Then s.WindowPositions.Save(Me) + If Not s.WindowPositions Is Nothing Then + s.WindowPositions.Save(Me) + End If + MyBase.OnFormClosing(e) End Sub