Webcam/capture device access (Windows only)

BlitzMax Forums/BlitzMax Programming/Webcam/capture device access (Windows only)

Anyone with a webcam, TV input or whatever fancy trying this?

http://www.blitzmax.com/codearcs/codearcs.php?code=1899

Please note: if it doesn't work for you, there's not much I can do, as it uses the ESCAPI library for access! I'd be interested to find out the results, though.

yes works perfect here (Notebook ASUS A7D With WebCam 1.3mPix)

works great here too..

another Asus laptop; A7J with integrated BisonCam)

Yup, works perfectly here - Logitech Quickcam.

Works here as well... desktop with Creative Live! webcam.

Works great on

Capture device [1] name: Conexant 2388x Video Capture
Capture device [2] name: Logitech QuickCam Pro 5000

but not on

Capture device [0] name: ATI Rage Theater Video Capture
but that might just be the machine, so no worry.

Now how to but this on a MiniB3D texture? :D

Works fine with my Creative Webcam pro

What are the advantages of using this over normal windows webcam commands? Like here.

Fine on my Sony Laptop's built in "Motion Eye" webcam. This DLL seems really easy to use - it's a pity though that getting a webcam to work cross-platform is so hard in BlitzMax!

Works perfectly on my Logitech Quickcam Express 2...(Athlon x2 3800, 1Gb RAM)

One problem with the escapi.dll. I tried loading the pixmap into a TImage to do some effects, but it didn't work. AFter much fiddling around, I noticed that the escapi.dll set the alpha chanel to 0. Is there any way to tell escapi to set the alpha to $FF or any way to automatically set the alpha with LoadImage? Right now, I need to loop through the pixmap and set the alpha of each pixel to $FF.

Works fine with my Logitech Quickcam thing-of-a-bob

cool, works on my cheap as chips chinese crap webcam.

Q. My webcam isn't great, plus it has lag AND poor framerate. Will another webcam improve this or is it some kind of USB or driver issue?

TomToad: not sure what's up there -- this works for me:

Type SimpleCapParams
	Field mTargetBuf:Byte Ptr ' Must be at least mWidth * mHeight * SizeOf(Int) of size! 
	Field mWidth
	Field mHeight
End Type

Global InitCOM () "C"
Global CountCaptureDevices () "C"
Global OpenCaptureDevice (device, scp:Byte Ptr) "C"
Global CloseCaptureDevice (device) "C"
Global GetCapture (device) "C"
Global CaptureDone (device) "C"
Global CaptureDeviceName (device, name:Byte Ptr, namelen) "C"
Global ESCAPIDLLVersion () "C"

Function SetupESCAPI ()

	esc = LoadLibraryA ("escapi.dll")
	
	If esc
	
		InitCOM					= GetProcAddress (esc, "initCOM")
		CountCaptureDevices		= GetProcAddress (esc, "countCaptureDevices")
		OpenCaptureDevice 		= GetProcAddress (esc, "initCapture")
		CloseCaptureDevice		= GetProcAddress (esc, "deinitCapture")
		GetCapture				= GetProcAddress (esc, "doCapture")
		CaptureDone				= GetProcAddress (esc, "isCaptureDone")
		CaptureDeviceName		= GetProcAddress (esc, "getCaptureDeviceName")
		ESCAPIDLLVersion		= GetProcAddress (esc, "ESCAPIDLLVersion")

		If InitCOM = Null Or CountCaptureDevices = Null Or OpenCaptureDevice = Null or..
			CloseCaptureDevice = Null Or GetCapture = Null Or CaptureDone = Null or..
				CaptureDeviceName = Null Or ESCAPIDLLVersion = Null
					DebugLog "Function missing!"
					Return 0
		EndIf

		InitCOM ()
		
		If ESCAPIDLLVersion () < $200
			DebugLog "Old DLL (needs version 2.0+)"
			Return 0
		EndIf
		
	Else
		DebugLog "Failed to open DLL"
		Return 0
	EndIf

	Return 1
	
End Function

Function CaptureDevice$ (device)
	Local cam:Byte [1024]
	CaptureDeviceName (device, cam, 1024)
	Return String.FromCString (cam)
End Function

If SetupESCAPI () = 0
	Notify "Error! Make sure escapi.dll is in same folder and capture device plugged in!"
	End
EndIf

For num = 0 Until CountCaptureDevices ()
	Print "Capture device [" + num + "] name: " + CaptureDevice (num)
Next

device = 0

' To list/select devices...

	'Repeat
	'	device = Int (Input ("Enter capture device number: "))
	'Until device > -1 And device < CountCaptureDevices ()

' Preferred target width/height (ESCAPI scales capture data to this)...

width = 320
height = 240

AppTitle = "Using " + CaptureDevice (device) + "..."

Graphics 640, 480 ', 32

' Data structure...

Local scp:SimpleCapParams = New SimpleCapParams

' A PixMap for captured data...

pix:TPixmap = CreatePixmap (width, height, PF_BGRA8888)

' Stick pixmap memory pointer into data structure...

scp.mTargetBuf	= PixmapPixelPtr (pix)
scp.mWidth		= width
scp.mHeight		= height

' Start capture process...

If OpenCaptureDevice (device, scp) = 0
	Print "Failed to initialise capture device!"
	End
EndIf

image = CreateImage (width, height)

SetClsColor 64, 128, 180

Repeat

	GetCapture (device)
	
	Repeat
		If KeyHit (KEY_ESCAPE) Then quit = True
	Until CaptureDone (device)

	' Draw PixMap to back buffer and grab into image...
	
	DrawPixmap pix, 0, 0
	GrabImage (image, 0, 0)
	
	Cls
	
	SetScale 4 * Float (MouseX ()) / GraphicsWidth (), 4 * Float (MouseY ()) / GraphicsHeight ()
	DrawImage image, MouseX (), MouseY ()
	
	Flip

Until quit = True

' Stop capture process...
	
CloseCaptureDevice (device)

End


Grey: It's probably just your webcam -- mine's crap too (it's slow and very dark). Apparently the EyeToy webcam works with Windows and it's built for low light/high speed operation. My local GameStation often sells them for a tenner or so, so I intend to pick one up and try it...


it's a pity though that getting a webcam to work cross-platform is so hard in BlitzMax!


I think that's really just dependent on the capture APIs available from the OS and how easy they are to implement.

Just to have a play around I slightly adapted the above example so you can spin around if you scroll the mouse. I'm feeling dizzy!

Type SimpleCapParams
	Field mTargetBuf:Byte Ptr ' Must be at least mWidth * mHeight * SizeOf(Int) of size! 
	Field mWidth
	Field mHeight
End Type

Global InitCOM () "C"
Global CountCaptureDevices () "C"
Global OpenCaptureDevice (device, scp:Byte Ptr) "C"
Global CloseCaptureDevice (device) "C"
Global GetCapture (device) "C"
Global CaptureDone (device) "C"
Global CaptureDeviceName (device, name:Byte Ptr, namelen) "C"
Global ESCAPIDLLVersion () "C"

Function SetupESCAPI ()

	esc = LoadLibraryA ("escapi.dll")
	
	If esc
	
		InitCOM					= GetProcAddress (esc, "initCOM")
		CountCaptureDevices		= GetProcAddress (esc, "countCaptureDevices")
		OpenCaptureDevice 		= GetProcAddress (esc, "initCapture")
		CloseCaptureDevice		= GetProcAddress (esc, "deinitCapture")
		GetCapture				= GetProcAddress (esc, "doCapture")
		CaptureDone				= GetProcAddress (esc, "isCaptureDone")
		CaptureDeviceName		= GetProcAddress (esc, "getCaptureDeviceName")
		ESCAPIDLLVersion		= GetProcAddress (esc, "ESCAPIDLLVersion")

		If InitCOM = Null Or CountCaptureDevices = Null Or OpenCaptureDevice = Null or..
			CloseCaptureDevice = Null Or GetCapture = Null Or CaptureDone = Null or..
				CaptureDeviceName = Null Or ESCAPIDLLVersion = Null
					DebugLog "Function missing!"
					Return 0
		EndIf

		InitCOM ()
		
		If ESCAPIDLLVersion () < $200
			DebugLog "Old DLL (needs version 2.0+)"
			Return 0
		EndIf
		
	Else
		DebugLog "Failed to open DLL"
		Return 0
	EndIf

	Return 1
	
End Function

Function CaptureDevice$ (device)
	Local cam:Byte [1024]
	CaptureDeviceName (device, cam, 1024)
	Return String.FromCString (cam)
End Function

If SetupESCAPI () = 0
	Notify "Error! Make sure escapi.dll is in same folder and capture device plugged in!"
	End
EndIf

For num = 0 Until CountCaptureDevices ()
	Print "Capture device [" + num + "] name: " + CaptureDevice (num)
Next

device = 0

' To list/select devices...

	'Repeat
	'	device = Int (Input ("Enter capture device number: "))
	'Until device > -1 And device < CountCaptureDevices ()

' Preferred target width/height (ESCAPI scales capture data to this)...

width = 320
height = 240

Global oldmousez = MouseZ()

AppTitle = "Using " + CaptureDevice (device) + "..."

Graphics 640, 480 ', 32

' Data structure...

Local scp:SimpleCapParams = New SimpleCapParams

' A PixMap for captured data...

pix:TPixmap = CreatePixmap (width, height, PF_BGRA8888)

' Stick pixmap memory pointer into data structure...

scp.mTargetBuf	= PixmapPixelPtr (pix)
scp.mWidth		= width
scp.mHeight		= height

' Start capture process...

If OpenCaptureDevice (device, scp) = 0
	Print "Failed to initialise capture device!"
	End
EndIf

image = CreateImage (width, height)
MidHandleImage(image)

SetClsColor 64, 128, 180

Repeat

	GetCapture (device)
	
	Repeat
		If KeyHit (KEY_ESCAPE) Then quit = True
	Until CaptureDone (device)

	' Draw PixMap to back buffer and grab into image...
	
	DrawPixmap pix, 0, 0
	GrabImage (image, 0, 0)
	
	Cls
	
	SetRotation((GetRotation()+(MouseZ()*3)) Mod 360)

	DrawImage image, MouseX (), MouseY ()
	
	Flip

Until quit = True

' Stop capture process...
	
CloseCaptureDevice (device)

End


Seb: nice!

I noticed that the escapi.dll set the alpha chanel to 0

I mentioned this to Jari, the developer, and he's going to [try and remember to] change this in the next update so it's solid instead.

Didn't think of using GrabImage(). Probably be a bit faster than writing to each individual pixel of the pixmap. Still would be better if the captured image originally had a solid alpha to begin with. :)
This is basically what I was trying to do. :)
' Thanks to Freak from the PureBasic forums for assistance!

Type SimpleCapParams
	Field mTargetBuf:Byte Ptr ' Must be at least mWidth * mHeight * SizeOf(Int) of size! 
	Field mWidth
	Field mHeight
End Type

Global InitCOM () "C"
Global CountCaptureDevices () "C"
Global OpenCaptureDevice (device, scp:Byte Ptr) "C"
Global CloseCaptureDevice (device) "C"
Global GetCapture (device) "C"
Global CaptureDone (device) "C"
Global CaptureDeviceName (device, name:Byte Ptr, namelen) "C"
Global ESCAPIDLLVersion () "C"

Function SetupESCAPI ()

	esc = LoadLibraryA ("escapi.dll")
	
	If esc
	
		InitCOM					= GetProcAddress (esc, "initCOM")
		CountCaptureDevices		= GetProcAddress (esc, "countCaptureDevices")
		OpenCaptureDevice 		= GetProcAddress (esc, "initCapture")
		CloseCaptureDevice		= GetProcAddress (esc, "deinitCapture")
		GetCapture				= GetProcAddress (esc, "doCapture")
		CaptureDone				= GetProcAddress (esc, "isCaptureDone")
		CaptureDeviceName		= GetProcAddress (esc, "getCaptureDeviceName")
		ESCAPIDLLVersion		= GetProcAddress (esc, "ESCAPIDLLVersion")

		If InitCOM = Null Or CountCaptureDevices = Null Or OpenCaptureDevice = Null or..
			CloseCaptureDevice = Null Or GetCapture = Null Or CaptureDone = Null or..
				CaptureDeviceName = Null Or ESCAPIDLLVersion = Null
					DebugLog "Function missing!"
					Return 0
		EndIf

		InitCOM ()
		
		If ESCAPIDLLVersion () < $200
			DebugLog "Old DLL (needs version 2.0+)"
			Return 0
		EndIf
		
	Else
		DebugLog "Failed to open DLL"
		Return 0
	EndIf

	Return 1
	
End Function

Function CaptureDevice$ (device)
	Local cam:Byte [1024]
	CaptureDeviceName (device, cam, 1024)
	Return String.FromCString (cam)
End Function

If SetupESCAPI () = 0
	Notify "Error! Make sure escapi.dll is in same folder and capture device plugged in!"
	End
EndIf

For num = 0 Until CountCaptureDevices ()
	Print "Capture device [" + num + "] name: " + CaptureDevice (num)
Next

device = 0

' To list/select devices...

	'Repeat
	'	device = Int (Input ("Enter capture device number: "))
	'Until device > -1 And device < CountCaptureDevices ()

' Preferred target width/height (ESCAPI scales capture data to this)...

width = 320
height = 240

AppTitle = "Using " + CaptureDevice (device) + "..."

Graphics width, height', 32

' Data structure...

Local scp:SimpleCapParams = New SimpleCapParams

' A PixMap for captured data...

pix:TPixmap = CreatePixmap (width, height, PF_BGRA8888)

pixlist:TList = CreateList()
Local drawpix:TImage
' Stick pixmap memory pointer into data structure...

scp.mTargetBuf	= PixmapPixelPtr (pix)
scp.mWidth		= width
scp.mHeight		= height

' Start capture process...

If OpenCaptureDevice (device, scp) = 0
	Print "Failed to initialise capture device!"
	End
EndIf
SetBlend ALPHABLEND

Repeat

	Cls

	GetCapture (device)
	
	Repeat
		If KeyHit (KEY_ESCAPE) Then quit = True
	Until CaptureDone (device)
	newpix:TImage = CreateImage(width,height)
	DrawPixmap pix,0,0
	GrabImage(newpix,0,0)
	ListAddFirst(pixlist,newpix)
	Local alpha:Float = 1.0
	For drawpix = EachIn pixlist
		SetAlpha alpha
		DrawImage drawpix, 0, 0
		alpha :* .5
	Next
	If CountList(pixlist) > 10 Then ListRemove(pixlist,drawpix)
	Flip

Until quit = True

' Stop capture process...
	
CloseCaptureDevice (device)

End

edit:To change device# to 0 since I orginally had it set to 1 because that's what my webcam is on. :)

edit again :This is pure madness. :)
' Thanks to Freak from the PureBasic forums for assistance!

Type SimpleCapParams
	Field mTargetBuf:Byte Ptr ' Must be at least mWidth * mHeight * SizeOf(Int) of size! 
	Field mWidth
	Field mHeight
End Type

Global InitCOM () "C"
Global CountCaptureDevices () "C"
Global OpenCaptureDevice (device, scp:Byte Ptr) "C"
Global CloseCaptureDevice (device) "C"
Global GetCapture (device) "C"
Global CaptureDone (device) "C"
Global CaptureDeviceName (device, name:Byte Ptr, namelen) "C"
Global ESCAPIDLLVersion () "C"

Function SetupESCAPI ()

	esc = LoadLibraryA ("escapi.dll")
	
	If esc
	
		InitCOM					= GetProcAddress (esc, "initCOM")
		CountCaptureDevices		= GetProcAddress (esc, "countCaptureDevices")
		OpenCaptureDevice 		= GetProcAddress (esc, "initCapture")
		CloseCaptureDevice		= GetProcAddress (esc, "deinitCapture")
		GetCapture				= GetProcAddress (esc, "doCapture")
		CaptureDone				= GetProcAddress (esc, "isCaptureDone")
		CaptureDeviceName		= GetProcAddress (esc, "getCaptureDeviceName")
		ESCAPIDLLVersion		= GetProcAddress (esc, "ESCAPIDLLVersion")

		If InitCOM = Null Or CountCaptureDevices = Null Or OpenCaptureDevice = Null or..
			CloseCaptureDevice = Null Or GetCapture = Null Or CaptureDone = Null or..
				CaptureDeviceName = Null Or ESCAPIDLLVersion = Null
					DebugLog "Function missing!"
					Return 0
		EndIf

		InitCOM ()
		
		If ESCAPIDLLVersion () < $200
			DebugLog "Old DLL (needs version 2.0+)"
			Return 0
		EndIf
		
	Else
		DebugLog "Failed to open DLL"
		Return 0
	EndIf

	Return 1
	
End Function

Function CaptureDevice$ (device)
	Local cam:Byte [1024]
	CaptureDeviceName (device, cam, 1024)
	Return String.FromCString (cam)
End Function

If SetupESCAPI () = 0
	Notify "Error! Make sure escapi.dll is in same folder and capture device plugged in!"
	End
EndIf

For num = 0 Until CountCaptureDevices ()
	Print "Capture device [" + num + "] name: " + CaptureDevice (num)
Next

device = 0

' To list/select devices...

	'Repeat
	'	device = Int (Input ("Enter capture device number: "))
	'Until device > -1 And device < CountCaptureDevices ()

' Preferred target width/height (ESCAPI scales capture data to this)...

width = 320
height = 240

AppTitle = "Using " + CaptureDevice (device) + "..."

Graphics width, height', 32

' Data structure...

Local scp:SimpleCapParams = New SimpleCapParams

' A PixMap for captured data...

pix:TPixmap = CreatePixmap (width, height, PF_BGRA8888)

pixlist:TList = CreateList()
Local drawpix:TImage
' Stick pixmap memory pointer into data structure...

scp.mTargetBuf	= PixmapPixelPtr (pix)
scp.mWidth		= width
scp.mHeight		= height

' Start capture process...

If OpenCaptureDevice (device, scp) = 0
	Print "Failed to initialise capture device!"
	End
EndIf
SetBlend ALPHABLEND

Repeat

	Cls

	GetCapture (device)
	
	Repeat
		If KeyHit (KEY_ESCAPE) Then quit = True
	Until CaptureDone (device)
	newpix:TImage = CreateImage(width,height)
	DrawPixmap pix,0,0
	GrabImage(newpix,0,0)
	ListAddFirst(pixlist,newpix)
	Local alpha:Float = 1.0
	Local zip:Int = 0
	For drawpix = EachIn pixlist
		If zip < 5
			zip :+ 1
		Else
			SetAlpha alpha
			DrawImage drawpix, 0, 0
			alpha :* .5
			zip = 0
		End If
	Next
	If CountList(pixlist) > 100 Then ListRemove(pixlist,drawpix)
	Flip

Until quit = True

' Stop capture process...
	
CloseCaptureDevice (device)

End


Works great with my Creative WebCam NX Ultra, both in 'standard' mode and through its VFW interface.

(Hm... How to freak out a user -- take a snapshot with their webcam if they have one, and use it somewhere in your background art. :-? )

Beaker:
What are the advantages of using this over normal windows webcam commands? Like here.


Never got that one to work on my system....

Sorry to bump my own thread, but I just tried this with my brother's Sony EyeToy camera using these drivers (unarchive, plug camera into USB port, tell Windows to install from the folder you unarchived into when it prompts for drivers). The difference is amazing when compared to my crappy webcam (excuse the decor):

CrapCam:


EyeToy:


The crappy webcam is very jerky, slow and laggy (maybe 10 frames per second at a guess, with perhaps a quarter second lag), while the EyeToy updates very nicely, pretty much in real time, maybe 25-30 FPS (with a very small lag indeed). My local GameStation gets EyeToy cameras in from time to time, for around £12 ($20?), so I'll be picking one of these up... they're great!

BTW TomToad -- that second example is very trippy!

well the eytoy cameras much better as the most webcam for the pc .

new webcams offer 30 fps @ 640/480 on usb 2.0 but i never
got 30 fps with this picturesize , only on 320/200.

i will checkout the software next time hope its better than mine.