Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Development

Reply
 
Thread Tools Search this Thread Display Modes
Old 7th January 2011, 22:25   #1  |  Link
osgZach
Registered User
 
Join Date: Feb 2009
Location: USA
Posts: 680
Using Avisynth inside a program/development questions

Hi all,

Been a while since I've posted any problems, etc.. Hopefully it won't be too difficult to get some answers. Sorry if these questions are noob-ish, but I am learning a lot of things about programming as I go.. I have tinkered with languages for a decade but could never settle on one, or get very far by myself since I lack the money for traditional/formal classes on Programming.

This is a very serious project with a real goal though, and I fully expect to invest Months of work in its realization.


I am currently in the beginning stages (writing the design document) of what I hope will be my first complete Windows program. I don't want to go too much into detail, except to say it is inspired by YATTA (Yet Another Telecide Tool for Anime) and is specifically geared towards Anime VFR sources. In the end I am hoping to end up with something similar to YATTA, but much easier to use/learn, and that has much better documentation.

The application will be developed in PureBasic (I just can't stand C/C++ sorry!) and although I have tried looking at YATTA's source code several times, I can't really decipher the PASCAL language stuff well enough to tell what it is doing.

I am guessing I am going to have to write or find a wrapper of some sort, in order to use Avisynth inside my program.. Basically I want to be able to load an AVS script, and then scan it (without rendering.. like Yatta Metrics Collector, or like VirtualDub's Video Analysis Pass).

That way I should be able to manipulate a video in anyway I deem necesarry, right? I'm going to capture output metrics from stuff like Telecide/TFM or any other filters that might warrant this, using the Debugstring- so I think I've got that part covered and know how to do it.

But before I embark upon the journey if either trying to write a wrapper myself (*pointers....groan), or understand the one written by Inc. (he also is working on a nice DirectShow wrapper for PB) I was wondering if there wasn't an easier way to work with Avisynth, Similar to how Virtualdub is used I suppose.

Perhaps implementing basic AVI loading for instance, and dealing with the frame served AVS script (using mpeg2source or w/e). As long as I could still call the frames individually, or zip through them to analyze real fast, etc.. There shouldn't be any accuracy concerns, right? However I am also aware that sometimes a program that is frameserved AVI by Avisynth, might still have issues with seeking within a stream, etc..


So I am wondering really what the best way to go is? Most of the data my program will work with and manipulate will be taken from DebugStrings for the most part (at least for the core functionality I want to implement.. don't know about future features yet).

I guess I'm just looking for general advice on how to approach this issue. If any other devs who use Avisynth in their programs want to comment with how they do it, how hard it was, or any other advice; that would be most appreciated.
osgZach is offline   Reply With Quote
Old 4th February 2011, 06:23   #2  |  Link
OvejaNegra
ekTOMBE STUDIOS
 
OvejaNegra's Avatar
 
Join Date: Dec 2005
Location: Cuba
Posts: 253
Im more or less on the same but with VisualBasic and i can speak (not with much experience) a little of C++.

The Staxrip load AVS frames (i think). take a look to the code.

Quote:
I guess I'm just looking for general advice on how to approach this issue. If any other devs who use Avisynth in their programs want to comment with how they do it, how hard it was, or any other advice; that would be most appreciated.
YES PLEASE!!
__________________
So, it works or not???
OvejaNegra is offline   Reply With Quote
Old 4th February 2011, 16:32   #3  |  Link
osgZach
Registered User
 
Join Date: Feb 2009
Location: USA
Posts: 680
Heh, I kind of wrote this thread off as "dead". I actually am currently trying to implement the AVIFILE API that Windows uses for AVI files. I got to the point where I could load a file, and grab some header information, but once I got a pointer to a packed DIB, I kind of was at a loss as to how to push it into an image. But I'm getting a little help from another PB Programmer currently and hopefully I will be able to do something with it.

Since you are using VB you should check this out. Maybe you can do something useful with it..
http://www.shrinkwrapvb.com/avihelp/avihelp.htm

The guy helping me also might be looking into Inc's Avisynth C API Wrapper for PB, so I guess if the above method fails for getting actual frames, hopefully he'll be able to simplify things for me.
Hope that link helps you, though.
osgZach is offline   Reply With Quote
Old 4th February 2011, 16:52   #4  |  Link
TheFluff
Excessively jovial fellow
 
Join Date: Jun 2004
Location: rude
Posts: 1,098
If you cannot figure out how to render a DIB to the screen on Windows, or if you cannot figure out how to convert it to whatever image format your environment uses, you probably shouldn't be doing anything programmatically with Avisynth at all. I suggest you a) learn some elementary knowledge about Microsoft's media formats and b) learn a real programming language.
TheFluff is offline   Reply With Quote
Old 4th February 2011, 17:27   #5  |  Link
osgZach
Registered User
 
Join Date: Feb 2009
Location: USA
Posts: 680
I would like to suggest, that if you can't say anything nice....

But seriously. Everybody starts somewhere. Sorry we're not all geniuses and use C/C++ like the rest of you

Last edited by osgZach; 4th February 2011 at 17:29.
osgZach is offline   Reply With Quote
Old 4th February 2011, 17:37   #6  |  Link
Groucho2004
 
Join Date: Mar 2006
Location: Barcelona
Posts: 5,033
Quote:
Originally Posted by osgZach View Post
Everybody starts somewhere.
Fair enough. However, you should start by using the native Avisynth API and not VFW.

Every plugin/filter I know is written that way using C/C++. That should give you a clue.
Groucho2004 is offline   Reply With Quote
Old 4th February 2011, 17:50   #7  |  Link
osgZach
Registered User
 
Join Date: Feb 2009
Location: USA
Posts: 680
I'm not writing a filter. My program will not do any filtering. All I need is to be able to display and step through a frame served AVI as the user dictates. The program will generate output files based on user input. That's all I'm doing.

Thus far I just got it to load and play through an AVS script. Had to stick a ConvertToRGB24 in the script to get that to happen though.. So I'm off to fix that part now (hopefully).

Last edited by osgZach; 4th February 2011 at 17:52.
osgZach is offline   Reply With Quote
Old 4th February 2011, 18:33   #8  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,407
The point is, if you want to process the output of an Avisynth script, it's much easier to do it using the Avisynth API, rather than doing it indirectly via VfW - unless you already have some more general reason for using the VfW interface.
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 4th February 2011, 22:00   #9  |  Link
osgZach
Registered User
 
Join Date: Feb 2009
Location: USA
Posts: 680
I understand that, Gavino.

I guess what I am trying to say is I am not really trying to "process" anything at this point. If I were to use the Avisynth API at this point, the only reason would be to call it directly to get a video frame and display it. Any output from the Avisynth filters I plan on using in any scripts (TFM, Tdecimate, Telecide or w/e) I can get via the Win32 DebugString. So in a sense, I feel it is much simpler for me to use the VfW API to load the script and display/step to a frame, especially given my lack of experience.

I would certainly like to be skilled enough to use the Avisynth API in the future, but I can't see a reason why I would absolutely need it for this particular program, in this case. I'm only interested in displaying the results of an Avisynth processed frame, i.e just like loading a script in VirtualDub to preview/tweak. My program will take user inputs for a Frame or Frame Range (Match these fields instead, Post Process this, Don't Decimate this Frame Range, Use this match pattern instead, etc. etc.) and then compile the resulting data and create a new Script that the program can send to a command line encoder, as well as generate the necesarry TimeCodes V1 file for muxing into an MKV, and any overrides files needed to VFR decimate the file.

For the time being, the VfW API provided by AVIFIL32.DLL seems to be the right tool for my skill level, and it can do what I need - win/win right?

Last edited by osgZach; 4th February 2011 at 22:04.
osgZach is offline   Reply With Quote
Old 4th February 2011, 22:54   #10  |  Link
TheFluff
Excessively jovial fellow
 
Join Date: Jun 2004
Location: rude
Posts: 1,098
Quote:
Originally Posted by osgZach View Post
I would like to suggest, that if you can't say anything nice....

But seriously. Everybody starts somewhere. Sorry we're not all geniuses and use C/C++ like the rest of you
No, really, I mean it. I'm a terrible excuse for a programmer myself, so I should know. A DIB is the simplest kind of image data you can get; it's just an RGB bitmap with some metadata tacked on (the only gotcha is that it's stored upside down). The Win32 API provides a lot of functions for interacting directly with DIB's, and information on how to do stuff with DIB's is readily available just a Google search away. If you cannot figure out what to do with it on your own, your chances of succeding in doing whatever you want to do is not very high. Start with something easier.
TheFluff is offline   Reply With Quote
Old 5th February 2011, 00:00   #11  |  Link
osgZach
Registered User
 
Join Date: Feb 2009
Location: USA
Posts: 680
It's not that I can't figure out what to do with it. It's that I'm new to API and Pointers and all that crap. I suck at learning anything decent from standard reference Docs. I've spent plenty of time on MSDN. I don't think like someone who has been programming for a few years, it takes time for me to wade through endless walls of syntax and API calls.

I am getting lots of helpful advice from another PB programmer, however. So I am nearly there. It is far from "not a real language", which is likely why my progress is so slow. I went with PB over something like VB precisely because I want to learn how to do this stuff. That and the development tools were way cheaper.

/shrug

Last edited by osgZach; 5th February 2011 at 00:02.
osgZach is offline   Reply With Quote
Old 5th February 2011, 06:34   #12  |  Link
OvejaNegra
ekTOMBE STUDIOS
 
OvejaNegra's Avatar
 
Join Date: Dec 2005
Location: Cuba
Posts: 253
with VB.net IS POSSSIBLE to process a DIB.
with VB6 IS POSSIBLE to process a DIB.
Take a look at the sources of staxrip and,well, ill find my old VB6 samples.
IS posible.
Calling to the api for things like this is very painfull with VB.net. Thats why i want write a wrapper using c++cli but i need some help with the AVS api.

this is from staxrip: it works

Quote:
Imports Microsoft.VisualBasic
Imports System
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports System.Drawing.Imaging
Imports System.Windows.Forms
Imports System.Reflection
Imports System.Diagnostics
Imports System.Text
Imports Microsoft.Win32



Public Class RegistryHelp
Public Shared CurrentUser As New RootKey(Registry.CurrentUser)
Public Shared LocalMachine As New RootKey(Registry.LocalMachine)
Public Shared ClassesRoot As New RootKey(Registry.ClassesRoot)

Private Shared ApplicationKey As String = "Software\" + Application.ProductName

Public Class RootKey
Private RootRegistryKey As RegistryKey

Public Sub New(ByVal rootKey As RegistryKey)
RootRegistryKey = rootKey
End Sub

Public Function GetValue(ByVal key As String, ByVal name As String) As Object
Dim ret As Object = Nothing
Dim subKey As RegistryKey = RootRegistryKey.OpenSubKey(key)

If Not subKey Is Nothing Then
ret = subKey.GetValue(name)
subKey.Close()
End If

Return ret
End Function

Public Function GetString(ByVal key As String, ByVal name As String) As String
Return DirectCast(GetValue(key, name), String)
End Function

Public Sub SetValue(ByVal key As String, ByVal name As String, ByVal value As Object)
Dim subKey As RegistryKey = RootRegistryKey.OpenSubKey(key, True)

If subKey Is Nothing Then
subKey = RootRegistryKey.CreateSubKey(key)
End If

subKey.SetValue(name, value)
subKey.Close()
End Sub

Public Sub DeleteKey(ByVal key As String)
Dim rk As RegistryKey = RootRegistryKey.OpenSubKey(key)

If Not rk Is Nothing Then
If rk.SubKeyCount = 0 Then
RootRegistryKey.DeleteSubKey(key)
Else
RootRegistryKey.DeleteSubKeyTree(key)
End If
End If
End Sub

Public Sub DeleteValue(ByVal key As String, ByVal name As String)
Dim rk As RegistryKey = RootRegistryKey.OpenSubKey(key, True)

If Not rk Is Nothing Then
rk.DeleteValue(name, False)
rk.Close()
End If
End Sub

Public Sub SetApplicationValue(ByVal name As String, ByVal value As Object)
SetValue(ApplicationKey, name, value)
End Sub

Public Function GetApplicationValue(ByVal name As String) As Object
Return GetValue(ApplicationKey, name)
End Function

Public Function GetApplicationString(ByVal name As String) As String
Return GetString(ApplicationKey, name)
End Function
End Class

Public Shared Sub SetAssociation(ByVal extNoDot As String)
Dim value As String = RegistryHelp.ClassesRoot.GetString("." + extNoDot, "")

If value Is Nothing OrElse value = "" Then
Dim rk As RegistryKey = Registry.ClassesRoot.CreateSubKey("." + extNoDot)
rk.SetValue("", extNoDot + "file")
rk.Close()
value = extNoDot + "file"
End If

Dim rk2 As RegistryKey = Registry.ClassesRoot.CreateSubKey( _
value + "\shell\" + Application.ProductName + "\command")

rk2.SetValue("", """" + Application.ExecutablePath + """ ""%1"" ""%n""")
rk2.Close()

Dim rk3 As RegistryKey = Registry.ClassesRoot.CreateSubKey(value + "\shell")
rk3.SetValue("", Application.ProductName)
rk3.Close()

RegistryHelp.ClassesRoot.DeleteKey(value + "\DefaultIcon")
RegistryHelp.CurrentUser.DeleteValue("Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\." + extNoDot, "Application")
End Sub

Public Shared Sub SetContextMenu(ByVal extNoDot As String)
Dim value As String = RegistryHelp.ClassesRoot.GetString("." + extNoDot, "")

If value Is Nothing OrElse value = "" Then
Dim rk As RegistryKey = Registry.ClassesRoot.CreateSubKey("." + extNoDot)
rk.SetValue("", extNoDot + "file")
rk.Close()
value = extNoDot + "file"
End If

Dim rk2 As RegistryKey = Registry.ClassesRoot.CreateSubKey( _
value + "\shell\" + Application.ProductName + "\command")

rk2.SetValue("", """" + Application.ExecutablePath + """ ""%1"" ""%n""")
rk2.Close()
End Sub

Public Shared Sub DeleteAssociation(ByVal extension As String)
Dim value As String = RegistryHelp.ClassesRoot.GetString("." + extension, "")
RegistryHelp.ClassesRoot.DeleteKey(value + "\shell\" + Application.ProductName)
End Sub
End Class

Public Class AVIFile
Public CropLeft, CropTop, CropRight, CropBottom As Integer

Private AviFile As IntPtr
Private FrameObject As IntPtr
Private AviStream As IntPtr
Private StreamInfo As AVISTREAMINFO
Private Control As Control
Private Sourcefile As String

Private FrameCountValue As Integer

Public ReadOnly Property FrameCount() As Integer
Get
Return FrameCountValue
End Get
End Property

Public ReadOnly Property FrameRate() As Single
Get
Return StreamInfo.dwRate / CSng(StreamInfo.dwScale)
End Get
End Property

Private FourCCValue As String

Public ReadOnly Property FourCC() As String
Get
Return FourCCValue
End Get
End Property

Public ReadOnly Property FrameSize() As Size
Get
Return New Size(CInt(StreamInfo.rcFrame.right), CInt(StreamInfo.rcFrame.bottom))
End Get
End Property

Private PositionValue As Integer

Public Property Position() As Integer
Get
Return PositionValue
End Get
Set(ByVal 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

Public Sub Open(ByVal fileName As String, ByVal c As Control)
Open(fileName)
Control = c
End Sub

Private Function GetFourCC(ByVal value As Integer) As String
Return Encoding.ASCII.GetString(BitConverter.GetBytes(value))
End Function

Public Sub Open(ByVal path As String)
Try
Sourcefile = path

AVIFileInit()

Dim OF_SHARE_DENY_WRITE As Integer = 32

If AVIFileOpen(AviFile, path, OF_SHARE_DENY_WRITE, IntPtr.Zero) <> 0 Then
Throw New Exception("AVIFileOpen failed")
End If

If AVIFileGetStream(AviFile, AviStream, 1935960438, 0) <> 0 Then 'FourCC for vids
Throw New Exception("AVIFileGetStream failed")
End If

FrameCountValue = AVIStreamLength(AviStream.ToInt32())

StreamInfo = New AVISTREAMINFO()

If AVIStreamInfo_(AviStream.ToInt32(), StreamInfo, Marshal.SizeOf(StreamInfo)) <> 0 Then
Throw New Exception("AVIStreamInfo failed")
End If

FourCCValue = GetFourCC(Convert.ToInt32(StreamInfo.fccHandler))

If FourCC = "YV12" Then
FrameObject = AVIStreamGetFrameOpen(AviStream, 1)

If FrameObject = IntPtr.Zero Then
Throw New Exception("Failed to decode YV12.")
End If
Else
FrameObject = AVIStreamGetFrameOpen(AviStream, 0)

If FrameObject = IntPtr.Zero Then
Throw New Exception("AVIStreamGetFrameOpen failed")
End If
End If
Catch ex As Exception
HandleException(ex)
End Try
End Sub

Public Sub HandleException(ByVal ex As Exception)
Dim sb As New StringBuilder
Dim yv12 As String = RegistryHelp.LocalMachine.GetString("SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32", "VIDC.YV12")

sb.AppendLine("message: " + ex.Message)
sb.AppendLine("yv12 decoder: " + yv12)
sb.AppendLine("FourCC: " + FourCCValue)
sb.AppendLine("yv12 decoder exists: ") '+ File.Exists(CommonDirs.System + yv12).ToString)
sb.AppendLine("colordepth: " + Screen.PrimaryScreen.BitsPerPixel.ToString)
sb.AppendLine("path: " + Sourcefile)

'If Filepath.GetExt(Sourcefile) = ".avs" Then
' If File.Exists(Sourcefile) Then
' sb.AppendLine("script: " + vbCrLf + vbCrLf + StringHelp.ReadFile(Sourcefile))
' Else
' sb.AppendLine("file does not exist!")
' End If
'End If

Throw New Exception(sb.ToString)
End Sub

Public Sub Close()
If Not FrameObject = IntPtr.Zero Then
AVIStreamGetFrameClose(FrameObject)
FrameObject = IntPtr.Zero
End If

If Not AviStream = IntPtr.Zero Then
AVIStreamRelease(AviStream)
AviStream = IntPtr.Zero
End If

If Not AviFile = IntPtr.Zero Then
AVIFileRelease(AviFile)
AviFile = IntPtr.Zero
End If

AVIFileExit()
End Sub

Public Sub Draw()
If Not Control Is Nothing AndAlso Control.Visible Then
Dim g As Graphics = Control.CreateGraphics()
Draw(g)
g.Dispose()
End If
End Sub

Public Sub Draw(ByVal g As Graphics)
Try
If Not Control Is Nothing AndAlso Control.Visible AndAlso Not FrameObject = IntPtr.Zero Then
Dim img As Image = GetBMPFromDib(New IntPtr(AVIStreamGetFrame(FrameObject, Position)))

If CropLeft = 0 AndAlso CropTop = 0 AndAlso CropRight = 0 AndAlso CropBottom = 0 Then
g.DrawImage(img, Control.ClientRectangle)
Else
Dim factorX As Single = CSng(Control.Width) / img.Width
Dim factorY As Single = CSng(Control.Height) / img.Height

Dim left As Single = CropLeft * factorX
Dim right As Single = CropRight * factorX
Dim top As Single = CropTop * factorY
Dim bottom As Single = CropBottom * factorY

Dim rectDest As RectangleF = New RectangleF()

rectDest.X = left
rectDest.Y = top
rectDest.Width = Control.Width - left - right
rectDest.Height = Control.Height - top - bottom

Dim rectSrc As Rectangle = New Rectangle()

rectSrc.X = CropLeft
rectSrc.Y = CropTop
rectSrc.Width = img.Width - CropLeft - CropRight
rectSrc.Height = img.Height - CropTop - CropBottom

g.DrawImage(img, rectDest, rectSrc, GraphicsUnit.Pixel)

Dim sb As SolidBrush = New SolidBrush(Color.White)

g.FillRectangle(sb, 0, 0, left, Control.Height)
g.FillRectangle(sb, 0, 0, Control.Width, top)
g.FillRectangle(sb, Control.Width - right, 0, right, Control.Height)
g.FillRectangle(sb, 0, Control.Height - bottom, Control.Width, bottom)

sb.Dispose()
End If
End If
Catch ex As Exception
HandleException(ex)
End Try
End Sub

Public Function GetBitmap() As Bitmap
Return GetBMPFromDib(New IntPtr(AVIStreamGetFrame(FrameObject, Position)))
End Function

Public Function GetBMPFromDib(ByVal pDIB As IntPtr) As Bitmap
Dim pPix As IntPtr = New IntPtr(pDIB.ToInt32() + Marshal.SizeOf(GetType(BITMAPINFOHEADER)))

Dim mi As MethodInfo = GetType(Bitmap).GetMethod("FromGDIplus", BindingFlags.Static Or BindingFlags.NonPublic)

Dim pBmp As IntPtr = IntPtr.Zero
Dim status As Integer = GdipCreateBitmapFromGdiDib(pDIB, pPix, pBmp)

Return CType(mi.Invoke(Nothing, New Object() {pBmp}), Bitmap)
End Function

__________________
So, it works or not???
OvejaNegra is offline   Reply With Quote
Old 5th February 2011, 06:37   #13  |  Link
OvejaNegra
ekTOMBE STUDIOS
 
OvejaNegra's Avatar
 
Join Date: Dec 2005
Location: Cuba
Posts: 253
with VB.net IS POSSSIBLE to process a DIB.
with VB6 IS POSSIBLE to process a DIB.
Take a look at the sources of staxrip and,well, ill find my old VB6 samples.
IS posible.
Calling to the api for things like this is very painfull with VB.net. Thats why i want write a wrapper using c++cli but i need some help with the AVS api.

this is from staxrip: it works

Quote:
Imports Microsoft.VisualBasic
Imports System
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports System.Drawing.Imaging
Imports System.Windows.Forms
Imports System.Reflection
Imports System.Diagnostics
Imports System.Text
Imports Microsoft.Win32



Public Class RegistryHelp
Public Shared CurrentUser As New RootKey(Registry.CurrentUser)
Public Shared LocalMachine As New RootKey(Registry.LocalMachine)
Public Shared ClassesRoot As New RootKey(Registry.ClassesRoot)

Private Shared ApplicationKey As String = "Software\" + Application.ProductName

Public Class RootKey
Private RootRegistryKey As RegistryKey

Public Sub New(ByVal rootKey As RegistryKey)
RootRegistryKey = rootKey
End Sub

Public Function GetValue(ByVal key As String, ByVal name As String) As Object
Dim ret As Object = Nothing
Dim subKey As RegistryKey = RootRegistryKey.OpenSubKey(key)

If Not subKey Is Nothing Then
ret = subKey.GetValue(name)
subKey.Close()
End If

Return ret
End Function

Public Function GetString(ByVal key As String, ByVal name As String) As String
Return DirectCast(GetValue(key, name), String)
End Function

Public Sub SetValue(ByVal key As String, ByVal name As String, ByVal value As Object)
Dim subKey As RegistryKey = RootRegistryKey.OpenSubKey(key, True)

If subKey Is Nothing Then
subKey = RootRegistryKey.CreateSubKey(key)
End If

subKey.SetValue(name, value)
subKey.Close()
End Sub

Public Sub DeleteKey(ByVal key As String)
Dim rk As RegistryKey = RootRegistryKey.OpenSubKey(key)

If Not rk Is Nothing Then
If rk.SubKeyCount = 0 Then
RootRegistryKey.DeleteSubKey(key)
Else
RootRegistryKey.DeleteSubKeyTree(key)
End If
End If
End Sub

Public Sub DeleteValue(ByVal key As String, ByVal name As String)
Dim rk As RegistryKey = RootRegistryKey.OpenSubKey(key, True)

If Not rk Is Nothing Then
rk.DeleteValue(name, False)
rk.Close()
End If
End Sub

Public Sub SetApplicationValue(ByVal name As String, ByVal value As Object)
SetValue(ApplicationKey, name, value)
End Sub

Public Function GetApplicationValue(ByVal name As String) As Object
Return GetValue(ApplicationKey, name)
End Function

Public Function GetApplicationString(ByVal name As String) As String
Return GetString(ApplicationKey, name)
End Function
End Class

Public Shared Sub SetAssociation(ByVal extNoDot As String)
Dim value As String = RegistryHelp.ClassesRoot.GetString("." + extNoDot, "")

If value Is Nothing OrElse value = "" Then
Dim rk As RegistryKey = Registry.ClassesRoot.CreateSubKey("." + extNoDot)
rk.SetValue("", extNoDot + "file")
rk.Close()
value = extNoDot + "file"
End If

Dim rk2 As RegistryKey = Registry.ClassesRoot.CreateSubKey( _
value + "\shell\" + Application.ProductName + "\command")

rk2.SetValue("", """" + Application.ExecutablePath + """ ""%1"" ""%n""")
rk2.Close()

Dim rk3 As RegistryKey = Registry.ClassesRoot.CreateSubKey(value + "\shell")
rk3.SetValue("", Application.ProductName)
rk3.Close()

RegistryHelp.ClassesRoot.DeleteKey(value + "\DefaultIcon")
RegistryHelp.CurrentUser.DeleteValue("Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\." + extNoDot, "Application")
End Sub

Public Shared Sub SetContextMenu(ByVal extNoDot As String)
Dim value As String = RegistryHelp.ClassesRoot.GetString("." + extNoDot, "")

If value Is Nothing OrElse value = "" Then
Dim rk As RegistryKey = Registry.ClassesRoot.CreateSubKey("." + extNoDot)
rk.SetValue("", extNoDot + "file")
rk.Close()
value = extNoDot + "file"
End If

Dim rk2 As RegistryKey = Registry.ClassesRoot.CreateSubKey( _
value + "\shell\" + Application.ProductName + "\command")

rk2.SetValue("", """" + Application.ExecutablePath + """ ""%1"" ""%n""")
rk2.Close()
End Sub

Public Shared Sub DeleteAssociation(ByVal extension As String)
Dim value As String = RegistryHelp.ClassesRoot.GetString("." + extension, "")
RegistryHelp.ClassesRoot.DeleteKey(value + "\shell\" + Application.ProductName)
End Sub
End Class

Public Class AVIFile
Public CropLeft, CropTop, CropRight, CropBottom As Integer

Private AviFile As IntPtr
Private FrameObject As IntPtr
Private AviStream As IntPtr
Private StreamInfo As AVISTREAMINFO
Private Control As Control
Private Sourcefile As String

Private FrameCountValue As Integer

Public ReadOnly Property FrameCount() As Integer
Get
Return FrameCountValue
End Get
End Property

Public ReadOnly Property FrameRate() As Single
Get
Return StreamInfo.dwRate / CSng(StreamInfo.dwScale)
End Get
End Property

Private FourCCValue As String

Public ReadOnly Property FourCC() As String
Get
Return FourCCValue
End Get
End Property

Public ReadOnly Property FrameSize() As Size
Get
Return New Size(CInt(StreamInfo.rcFrame.right), CInt(StreamInfo.rcFrame.bottom))
End Get
End Property

Private PositionValue As Integer

Public Property Position() As Integer
Get
Return PositionValue
End Get
Set(ByVal 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

Public Sub Open(ByVal fileName As String, ByVal c As Control)
Open(fileName)
Control = c
End Sub

Private Function GetFourCC(ByVal value As Integer) As String
Return Encoding.ASCII.GetString(BitConverter.GetBytes(value))
End Function

Public Sub Open(ByVal path As String)
Try
Sourcefile = path

AVIFileInit()

Dim OF_SHARE_DENY_WRITE As Integer = 32

If AVIFileOpen(AviFile, path, OF_SHARE_DENY_WRITE, IntPtr.Zero) <> 0 Then
Throw New Exception("AVIFileOpen failed")
End If

If AVIFileGetStream(AviFile, AviStream, 1935960438, 0) <> 0 Then 'FourCC for vids
Throw New Exception("AVIFileGetStream failed")
End If

FrameCountValue = AVIStreamLength(AviStream.ToInt32())

StreamInfo = New AVISTREAMINFO()

If AVIStreamInfo_(AviStream.ToInt32(), StreamInfo, Marshal.SizeOf(StreamInfo)) <> 0 Then
Throw New Exception("AVIStreamInfo failed")
End If

FourCCValue = GetFourCC(Convert.ToInt32(StreamInfo.fccHandler))

If FourCC = "YV12" Then
FrameObject = AVIStreamGetFrameOpen(AviStream, 1)

If FrameObject = IntPtr.Zero Then
Throw New Exception("Failed to decode YV12.")
End If
Else
FrameObject = AVIStreamGetFrameOpen(AviStream, 0)

If FrameObject = IntPtr.Zero Then
Throw New Exception("AVIStreamGetFrameOpen failed")
End If
End If
Catch ex As Exception
HandleException(ex)
End Try
End Sub

Public Sub HandleException(ByVal ex As Exception)
Dim sb As New StringBuilder
Dim yv12 As String = RegistryHelp.LocalMachine.GetString("SOFTWARE\Microsoft\Windows NT\CurrentVersion\Drivers32", "VIDC.YV12")

sb.AppendLine("message: " + ex.Message)
sb.AppendLine("yv12 decoder: " + yv12)
sb.AppendLine("FourCC: " + FourCCValue)
sb.AppendLine("yv12 decoder exists: ") '+ File.Exists(CommonDirs.System + yv12).ToString)
sb.AppendLine("colordepth: " + Screen.PrimaryScreen.BitsPerPixel.ToString)
sb.AppendLine("path: " + Sourcefile)

'If Filepath.GetExt(Sourcefile) = ".avs" Then
' If File.Exists(Sourcefile) Then
' sb.AppendLine("script: " + vbCrLf + vbCrLf + StringHelp.ReadFile(Sourcefile))
' Else
' sb.AppendLine("file does not exist!")
' End If
'End If

Throw New Exception(sb.ToString)
End Sub

Public Sub Close()
If Not FrameObject = IntPtr.Zero Then
AVIStreamGetFrameClose(FrameObject)
FrameObject = IntPtr.Zero
End If

If Not AviStream = IntPtr.Zero Then
AVIStreamRelease(AviStream)
AviStream = IntPtr.Zero
End If

If Not AviFile = IntPtr.Zero Then
AVIFileRelease(AviFile)
AviFile = IntPtr.Zero
End If

AVIFileExit()
End Sub

Public Sub Draw()
If Not Control Is Nothing AndAlso Control.Visible Then
Dim g As Graphics = Control.CreateGraphics()
Draw(g)
g.Dispose()
End If
End Sub

Public Sub Draw(ByVal g As Graphics)
Try
If Not Control Is Nothing AndAlso Control.Visible AndAlso Not FrameObject = IntPtr.Zero Then
Dim img As Image = GetBMPFromDib(New IntPtr(AVIStreamGetFrame(FrameObject, Position)))

If CropLeft = 0 AndAlso CropTop = 0 AndAlso CropRight = 0 AndAlso CropBottom = 0 Then
g.DrawImage(img, Control.ClientRectangle)
Else
Dim factorX As Single = CSng(Control.Width) / img.Width
Dim factorY As Single = CSng(Control.Height) / img.Height

Dim left As Single = CropLeft * factorX
Dim right As Single = CropRight * factorX
Dim top As Single = CropTop * factorY
Dim bottom As Single = CropBottom * factorY

Dim rectDest As RectangleF = New RectangleF()

rectDest.X = left
rectDest.Y = top
rectDest.Width = Control.Width - left - right
rectDest.Height = Control.Height - top - bottom

Dim rectSrc As Rectangle = New Rectangle()

rectSrc.X = CropLeft
rectSrc.Y = CropTop
rectSrc.Width = img.Width - CropLeft - CropRight
rectSrc.Height = img.Height - CropTop - CropBottom

g.DrawImage(img, rectDest, rectSrc, GraphicsUnit.Pixel)

Dim sb As SolidBrush = New SolidBrush(Color.White)

g.FillRectangle(sb, 0, 0, left, Control.Height)
g.FillRectangle(sb, 0, 0, Control.Width, top)
g.FillRectangle(sb, Control.Width - right, 0, right, Control.Height)
g.FillRectangle(sb, 0, Control.Height - bottom, Control.Width, bottom)

sb.Dispose()
End If
End If
Catch ex As Exception
HandleException(ex)
End Try
End Sub

Public Function GetBitmap() As Bitmap
Return GetBMPFromDib(New IntPtr(AVIStreamGetFrame(FrameObject, Position)))
End Function

Public Function GetBMPFromDib(ByVal pDIB As IntPtr) As Bitmap
Dim pPix As IntPtr = New IntPtr(pDIB.ToInt32() + Marshal.SizeOf(GetType(BITMAPINFOHEADER)))

Dim mi As MethodInfo = GetType(Bitmap).GetMethod("FromGDIplus", BindingFlags.Static Or BindingFlags.NonPublic)

Dim pBmp As IntPtr = IntPtr.Zero
Dim status As Integer = GdipCreateBitmapFromGdiDib(pDIB, pPix, pBmp)

Return CType(mi.Invoke(Nothing, New Object() {pBmp}), Bitmap)
End Function

>TOO LONG, it does not fit żany place where i can paste it?
__________________
So, it works or not???
OvejaNegra is offline   Reply With Quote
Old 6th February 2011, 23:42   #14  |  Link
osgZach
Registered User
 
Join Date: Feb 2009
Location: USA
Posts: 680
If you have trouble with something specific that you don't understand, pasting that little bit of code will probably get you more receptive help. (instead of just pasting a whole thing).

For what its worth, if you can understand Pascal, you might want to look at YATTA's source code repository on Google, under the G3 Trunk. If you want to write a wrapper, I certainly don't envy your task. Inc. Also wrote an Avisynth C API wrapper for PureBasic, I think he posted it somewhere here on the forums. Studying those might give you some clues, but you'd probably get better help writing a wrapper by asking in a dedicated programming forum, with a specific question about something you are having problems with.
osgZach is offline   Reply With Quote
Old 8th February 2011, 00:27   #15  |  Link
OvejaNegra
ekTOMBE STUDIOS
 
OvejaNegra's Avatar
 
Join Date: Dec 2005
Location: Cuba
Posts: 253
i pasted that code for you , maybe you can use it. it works for me.
__________________
So, it works or not???
OvejaNegra is offline   Reply With Quote
Old 8th February 2011, 21:03   #16  |  Link
osgZach
Registered User
 
Join Date: Feb 2009
Location: USA
Posts: 680
Oh, well I don't really know/use VB.. but maybe I can find something useful.

Happen to have a BITMAPINFOHEADER structure I could look at? (if you defined your own?)

Still having that issue with having to tack a "ConvertToRGB24" onto the end of scripts, but they do load and I can frame step forward and backward.. Since its just for preview purposes, I suppose I could just leave it as is and be happy that its working, just have the program throw the Convert in when it generates the preview script, and leave it out of generated scripts for actual processing.

Hopefully won't cause any image quality issues.

Last edited by osgZach; 8th February 2011 at 22:07.
osgZach is offline   Reply With Quote
Reply

Tags
api, avisynth, purebasic, vfr, wrapper

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 07:59.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2020, vBulletin Solutions Inc.