B3DHLP.dll in BlitzMax Help

BlitzMax Forums/BlitzMax Programming/B3DHLP.dll in BlitzMax Help

Stickman(Posted 2016) [#1]
Hello all
Been a while since Iv been here , Im a former B3D user and all
New to Blitz Max .

Currently I'm trying to get the B3DHLP.dll to load AVI frames into Blitz Max to work .

I got this working in another IDE called XOJO , and it worked great.

So Far in Bmx I seem to have things going but can't seem to
get the "AVIGETFRAME" to load .

In XoJo I used a MemoryBlock to load the frame , basically same thing as a Ptr or Bank In Blitz I think .

In my code Im not sure what the p_bits and the AVIGETFRAME variable needs to be ... Byte Ptr , Bank , Int ?????

Any help would be grateful and sorry if my code is
a little sloppy , just using this to see how things work in Bmx .

here is info about the .dll
dll info
here is a link to the B3DHLP.dll

And of course some code ( can't expect much help with out it )
... Feels good to be a Blitzer again :)

Import maxgui.Drivers
Import pub.Win32

lib = LoadLibraryA ("B3DHLP.dll")

Global OpenAVI:Int(f$z) = GetProcAddress (lib, "AVIOPEN")
Global AVIGetFrameRate:Int(AVIObject:Int) = GetProcAddress(lib, "AVIGETFRAMERATE")
Global AVIGetTotalFrames:Int(AVIObject:Int) = GetProcAddress(lib, "AVIGETTOTALFRAMES")

Global AVIGetImageSize:Int(AVIObject:Int) = GetProcAddress(lib, "AVIGETIMAGESIZE")
Global AVIGetWidth:Int(AVIObject:Int) = GetProcAddress(lib, "AVIGETWIDTH")
Global AVIGetHeight:Int(AVIObject:Int) = GetProcAddress(lib, "AVIGETHEIGHT")
Global AVIClose:Int(AVIObject:Int) = GetProcAddress(lib, "AVICLOSE")

'Don't know what variable to make these 
Global AVIGetFrame:Int(AVIObject:Int, Pos:Int) = GetProcAddress(lib, "AVIGETFRAME")
Global p_bits:Int
'????????????????

Global hAVI:Int, FrameSize:Int, AVIRate:Int, FrameWidth:Int, FrameHeight:Int, AVIDuration:Int



Global Window1:TGadget = CreateWindow("My Project", 100, 100, 800, 600, Null, WINDOW_TITLEBAR | WINDOW_RESIZABLE | WINDOW_CENTER | WINDOW_CLIENTCOORDS | WINDOW_STATUS)

Local Button1:TGadget = CreateButton("OpenAVI", 10, 260, 96, 24, Window1, BUTTON_OK)

Local Canvas1:TGadget = CreateCanvas(10, 10, 320, 240, Window1)

Local Textfield1:TGadget = CreateTextField(110, 260, 120, 22, Window1)

Local TextArea1:TGadget = CreateTextArea(110, 290, 120, 120, Window1)


Global q:Int = 0
Global f:String = ""

CreateTimer 60
	
Repeat
WaitEvent()
SetStatusText Window1, CurrentEvent.ToString()
		
		
Select EventID()
		
	Case EVENT_TIMERTICK
		RedrawGadget Canvas1

	Case EVENT_GADGETACTION
		
		Select EventSource()
			Case Button1
				q = 1 - q
				f = RequestFile("Select AVI File", "avi,AVI")
				
				hAVI = OpenAVI(f)
				AVIRate = AVIGetFrameRate(hAVI)
				AVIDuration = AVIGetTotalFrames(hAVI)
				
				p_bits = AVIGetFrame(hAVI, 0)
				
                                'Blocked out till a frame is loaded or it crashes
				'FrameSize = AVIGetImageSize(hAVI)
				'FrameWidth = AVIGetWidth(hAVI)
				'FrameHeight = AVIGetHeight(hAVI)
			    
				SetGadgetText(Textfield1, "AVI Oppened")
				AddTextAreaText(TextArea1, "Rate " + AVIRate + "~n")
				AddTextAreaText(TextArea1, "Duration " + AVIDuration + "~n")
				
				AddTextAreaText(TextArea1, "Size " + FrameSize + "~n")
				AddTextAreaText(TextArea1, "Width " + FrameWidth + "~n")
				AddTextAreaText(TextArea1, "Height " + FrameHeight + "~n")
				AddTextAreaText(TextArea1, "Compleat~n")
				
		EndSelect

	Case EVENT_GADGETPAINT

		g = CanvasGraphics(Canvas1)
		SetGraphics g
		Cls
		        
		'This is just for testing
		If q = 1 Then
			DrawText "AVI", 0, 0
		End If
				
		Flip
			
		
		
	Case EVENT_WINDOWCLOSE, EVENT_APPTERMINATE
			
		If hAVI <> Null Then AVIClose(hAVI)
		FreeLibrary (Lib)
			
		End
EndSelect
Forever



col(Posted 2016) [#2]
Hiya,

I'm sure for dll's you should be using the __stdcall convention. I have used dll's that require the __cdecl convention but they are the exception as opposed to the norm. Fortunately in BlitzMax we can specify the calling convention and __stdcall equates to "Win32" in BlitzMax. If you have the wrong calling convention then the stack gets screwed up when returning from the function. Sometimes this has a noticeable effect further down in the code, sometimes you see an error immediately.

So for all the dll functions that you want to use add "Win32" after the function definition, for eg...

Global OpenAVI:Int(f$z)"Win32" = GetProcAddress (lib, "AVIOPEN")
Global AVIGetFrameRate:Int(AVIObject:Int)"Win32" = GetProcAddress(lib, "AVIGETFRAMERATE")
etc...


I'm not tried your code so there may be other issues too.

ps. the BlitzMax equivalent of the __cdecl convention is "C" as opposed to "Win32" and if you don't specify a calling convention, as in your example code above, then the "C" is the default.


Stickman(Posted 2016) [#3]
Ok cool will give this a try when i get hame tonight.


Stickman(Posted 2016) [#4]
Yep That did it ... Thanks a Lot Dave .


Stickman(Posted 2016) [#5]
Well maby not out of the woods yet ...
Just realized that the AVIGETFRAME returns a byte value
from 1 to 256 and blitz bytes are from 0 to 255

I tried using a bitshift on a Int ptr ...somthing like.
& $FFFF ....that gave me same results as the byte ptr .

Oh well . hope sombody reads this and can help me figure
this onne out .


grable(Posted 2016) [#6]
If its larger than 255 then its not a Byte (8-bits) really.

After looking through the samples on that page, AVIGetFrame seems to return a pointer to the pixels of a frame.
Maybe AVIGetImageSize returns the total size of a frame, and you can use that to copy it over to a TPixmap or something.

Figuring out the pixelformat would be your next step.

AVIBltFrameToTexture/Image gets a DC from something, probably the internal DDrawSurface of the image/texture, and then StretchDIBits the frame over.
So it looks like you would have to reimplement it...


Stickman(Posted 2016) [#7]
I have this working in another programe ( XoJo ) and it works fine ....
So I did a little research and found that XoJo's MemoryBlock.Byte
actualy stores the ByteValues as Integers and returns the Value as a Byte ????

Ya let that spin around your head a Minute .

So all I need to do is make that Happen in Blitz .... Sounds Easy.

So now where do I start ????
Int Ptr ...Then What ?????


grable(Posted 2016) [#8]
I have tried it on all the AVI files i have (not that many) but it fails to get Image Size and Frame, both returning 0.
The other stats return fine, like its Dimensions, Duration and Rate.

Do you have a link to a working AVI file i can try it on perhaps?

This is what i have so far, notice that i assume the frame is 32-bits per pixel which is unlikely.
If it gets a pointer to a frame it simply copies it over to a pixmap and tries to draw it.



Stickman(Posted 2016) [#9]
Cool Grable ,

Was just working with Pixmaps myself and got it to work using
CreateStaticPixmap using the p_bits with a Format of PF_RGB888
then used loadImage to load the New Pixmap.

Also to get the Image Size and FrameWidth/Height you have to have
AVIGetFrame Before the call to AVIGetWidth/Height/Size.

I guess the Frame has to be loaded before it can tell what size ,etc it is.

Here is what I got working ( copied some of your coding to make it more official ) But using CreateStaticPixmap() and loadImage() instead

Not sure what way is faster but got it working non the less ....
With out this , converting all my code from XoJo to Blitz was meaningless.

Thanks a Million Grable .


SuperStrict

Import maxgui.Drivers
Import pub.Win32

Global lib:Int = LoadLibraryA ("B3DHLP.dll")

Global AVIOpenLib:Int() "win32" = GetProcAddress (lib, "AVIOPENLIB")
Global AVICloseLib:Int() "win32" = GetProcAddress (lib, "AVICLOSELIB")
Global OpenAVI:Int(f$z) "Win32" = GetProcAddress (lib, "AVIOPEN")
Global AVIGetFrameRate:Int(AVIObject:Int) "Win32" = GetProcAddress(lib, "AVIGETFRAMERATE")
Global AVIGetTotalFrames:Int(AVIObject:Int) "Win32" = GetProcAddress(lib, "AVIGETTOTALFRAMES")
Global AVIGetFrame:Int Ptr(AVIObject:Int, Pos:Int) "Win32" = GetProcAddress(lib, "AVIGETFRAME")
Global AVIGetImageSize:Int(AVIObject:Int) "Win32" = GetProcAddress(lib, "AVIGETIMAGESIZE")
Global AVIGetWidth:Int(AVIObject:Int) "Win32" = GetProcAddress(lib, "AVIGETWIDTH")
Global AVIGetHeight:Int(AVIObject:Int) "Win32" = GetProcAddress(lib, "AVIGETHEIGHT")
Global AVIClose:Int(AVIObject:Int) "Win32" = GetProcAddress(lib, "AVICLOSE")
Global FreePointer(p:Byte Ptr) "win32" = GetProcAddress(lib, "FREEPOINTER")
Global ReleaseDLL() "win32" = GetProcAddress( lib, "RELEASEDLL")
 
Global p_bits:Int Ptr

Global hAVI:Int, FrameSize:Int, AVIRate:Int, FrameWidth:Int, FrameHeight:Int, AVIDuration:Int

Global Window1:TGadget = CreateWindow("My Project", 100, 100, 800, 600, Null, WINDOW_TITLEBAR | WINDOW_RESIZABLE | WINDOW_CENTER | WINDOW_CLIENTCOORDS | WINDOW_STATUS)

Local Button1:TGadget = CreateButton("OpenAVI", 10, 260, 96, 24, Window1, BUTTON_OK)

Local Canvas1:TGadget = CreateCanvas(10, 10, 320, 240, Window1)

Local Textfield1:TGadget = CreateTextField(110, 260, 420, 22, Window1)

Local TextArea1:TGadget = CreateTextArea(110, 290, 120, 120, Window1)


Global f:String
Global im:TImage
Global pm:TPixmap

CreateTimer 60
AVIOpenLib()

Repeat
WaitEvent()
SetStatusText Window1, CurrentEvent.ToString()
		
		
Select EventID()
		
	Case EVENT_TIMERTICK
		RedrawGadget Canvas1

	Case EVENT_GADGETACTION
		
		Select EventSource()
			Case Button1
				f = RequestFile("Select AVI File", "AVI Files:avi")
				
				hAVI = OpenAVI(f)
				p_bits = AVIGetFrame(hAVI, 0)
				AVIRate = AVIGetFrameRate(hAVI)
				AVIDuration = AVIGetTotalFrames(hAVI)
				FrameWidth = AVIGetWidth(hAVI)
				FrameHeight = AVIGetHeight(hAVI)
				FrameSize = AVIGetImageSize(hAVI)
 
				If p_bits Then
                 pm:TPixmap = CreateStaticPixmap(p_bits, FrameWidth, FrameHeight, FrameWidth * 3, PF_RGB888)
				 im = LoadImage(pm)
                 FreePointer(p_bits)
				End If
				
				SetGadgetText(Textfield1, "AVI Loaded")
				AddTextAreaText(TextArea1, "Rate " + AVIRate + "~n")
				AddTextAreaText(TextArea1, "Duration " + AVIDuration + "~n")
				AddTextAreaText(TextArea1, "Size " + FrameSize + "~n")
				AddTextAreaText(TextArea1, "Width " + FrameWidth + "~n")
				AddTextAreaText(TextArea1, "Height " + FrameHeight + "~n")
				AddTextAreaText(TextArea1, "Compleat~n")
				
		EndSelect

	Case EVENT_GADGETPAINT

		SetGraphics CanvasGraphics(Canvas1)
		Cls
		        
		'This is just for testing
		If im Then DrawImage(im, 0, 0)
				
		Flip
			
		
		
	Case EVENT_WINDOWCLOSE, EVENT_APPTERMINATE
			
		If hAVI Then AVIClose(hAVI)
		AVICloseLib()
		ReleaseDLL()
		FreeLibrary(Lib)
			
		End
EndSelect
Forever 



grable(Posted 2016) [#10]
I still cant get FrameSize or Frame though. I guess the original API is rather picky about what files it can read.

Just a heads up, CreateStaticPixmap uses the pointer supplied directly, so you cant free it until your done with the pixmap itself (which is why i did a copy).

Glad you got it to work at least :)


Stickman(Posted 2016) [#11]
Ok , didn't know that with CreateStaticPixMap

Im creating an Image Stacking software program for
Astronomy .

How it works is you use a Small SCTV camera in place of
an eyepiece on a telescope then take an short 1 to 5 min AVI
of what ever the telescope camera sees ,

Then you load that AVI and stack each frame , the end results
are amazing .....

This program will also be able to do live stacking as well ,

the end results can look something like this .....
This Image was a LIVE stack of about 2min , you see this
live on a TV screen .

This type of viewing is known as EAA ( Electronic Assisted Astronomy )




col(Posted 2016) [#12]
Not meaning to derail the thread but did you take that 'image' yourself? That is an awesome pic!
I remember when I first saw Saturn through a telescope, I mean you know it's out there somewhere right, you read about it in books etc, but to actually see it with your own eyes is something completely different.


Stickman(Posted 2016) [#13]
No I didn't take that Pic , I just scrambled to look for one on the Forums , but I did take this one .....
Its a 2 Min Stack of the M57 galaxy....

If anyone is Interested there is a lot of info and PLENTY of Images
on this Forum CLOUDY NIGHTS
I go by the user name Submission there.