Capture Include (Webcams, DVB-T ...)
Verfasst: 16.06.2010 16:39
Ich hatte ein bisschen Langeweile und hab im Forum gesehen das das Thema WebCam - Aufnahme usw. ein paar mal angeschnitten wurde. Deshalb hab ich mal ein kleines Include geschrieben um z.B. eine WebCam anzuzeigen, aufzuzeichnen (AVI mit/ohne Ton), Einzelbilder zu schießen, Live - Manipulation des Videostreams und des Audiostream, Vorschau ein/ausschalten. Vielleicht kann ichs ja mal selbst brauchen
Am Besten selbst mal ansehen und ein bisschen damit spielen, vielleicht programmiere ich in den nächsten Tagen ein kleines Beispiel dazu.
Bei Bugs, Unklarheiten bei der Verwendung, Verbesserungsvorschläge einfach hier melden
Gruß, Alex

Am Besten selbst mal ansehen und ein bisschen damit spielen, vielleicht programmiere ich in den nächsten Tagen ein kleines Beispiel dazu.
Bei Bugs, Unklarheiten bei der Verwendung, Verbesserungsvorschläge einfach hier melden

Gruß, Alex
Code: Alles auswählen
; ------------------------------------------------------------------------------------
; Capture - Framework
; Author: Alexander Aigner
; PB 4.4+ x86/x64 Ascii/Unicode
; ------------------------------------------------------------------------------------
; ------------------------------------------------------------------------------------
; Info/Links:
; ------------------------------------------------------------------------------------
; Der Source sollte mit allem laufen was sich über den MS WDM - Treiber ansprechen lässt,
; zB. WebCams, DVB-T Empfänger, ...
; Der Source wurde unter Win 7 Home Premium x64 entwickelt und getestet.
; Vorlage:
; http://www.purebasic.fr/german/viewtopic.php?t=22579&start=5
; Mulitmedia Messages:
; http://msdn.microsoft.com/en-us/library/dd743599%28v=VS.85%29.aspx
; VideoStream - Callback:
; http://msdn.microsoft.com/en-us/library/dd797759%28v=VS.85%29.aspx
; VideoHDR - Struktur:
; http://msdn.microsoft.com/en-us/library/dd757688%28v=VS.85%29.aspx
; WaveStream - Callback:
; http://msdn.microsoft.com/en-us/library/dd797760%28v=VS.85%29.aspx
; WaveHDR - Struktur:
; http://msdn.microsoft.com/en-us/library/dd743837%28v=VS.85%29.aspx
; ------------------------------------------------------------------------------------
; Compilercheck
; ------------------------------------------------------------------------------------
EnableExplicit
CompilerIf #PB_Compiler_Thread = #False
CompilerError "Enable Threadsafe"
CompilerEndIf
CompilerIf (#PB_Compiler_OS <> #PB_OS_Windows)
CompilerError "Unsupported OS"
CompilerEndIf
; ------------------------------------------------------------------------------------
; Konstanten
; ------------------------------------------------------------------------------------
Enumeration ; Konstanten für die SampleRate bei den Audio-Optionen
#Capture_Audio_8kHz
#Capture_Audio_11kHz
#Capture_Audio_22kHz
#Capture_Audio_44kHz
EndEnumeration
Enumeration ; Callbacktypen für VideoCallback
#Capture_Video_RawDataCallback
#Capture_Video_ImageCallback ; Nur im RGB 24 Modus!
EndEnumeration
; ------------------------------------------------------------------------------------
; Strukturen, Prototypen und andere Internals
; ------------------------------------------------------------------------------------
Prototype _Capture_Callback(CFrame)
Structure RGB_24
r.a
g.a
b.a
EndStructure
Structure VIDEOHDR
*lpData
dwBufferLength.l
dwBytesUsed.l
dwTimeCaptured.l
dwUser.l
dwFlags.l
*dwReserved[4]
EndStructure
; Structure WAVEHDR
; *lpData
; dwBufferLength;
; dwBytesRecorded;
; *dwUser
; dwFlags.l
; dwLoops.l
; *lpNext.WAVEHDR
; reserved.l
; EndStructure
Structure CAPTUREPARAMS
dwRequestMicroSecPerFrame.l
fMakeUserHitOKToCapture.l
wPercentDropForError.l
fYield.l
dwIndexSize.l
wChunkGranularity.l
fUsingDOSMemory.l
wNumVideoRequested.l
fCaptureAudio.l
wNumAudioRequested.l
vKeyAbort.l
fAbortLeftMouse.l
fAbortRightMouse.l
fLimitEnabled.l
wTimeLimit.l
fMCIControl.l
fStepMCIDevice.l
dwMCIStartTime.l
dwMCIStopTime.l
fStepCaptureAt2x.l
wStepCaptureAverageFrames.l
dwAudioBufferSize.l
fDisableWriteCache.l
AVStreamMaster.l
EndStructure
Structure Capture_Data ; Capture - Daten
psVideoFormat.BITMAPINFO ; Video - Info
avicap32.i ; avicap DLL handle
hwndC.i ; Capturing HWND
ViewData.Rect ; Anzeige Position
WinID.i ; Window ID
SnapShot.i ; aktueller Snapshot
Capture.CAPTUREPARAMS ; Video - Aufnahmeoptionen
CAudio.WAVEFORMATEX ; Audio - Optionen
*CB._Capture_Callback ; Image Bearbeitungs - Callback
EndStructure
Prototype WaveStreamCallback(hWnd, *lpWHdr.WAVEHDR)
Prototype VideoStreamCallback(hWnd, *lpVHdr.VIDEOHDR)
Global WCCapture.Capture_Data
Procedure _Capture_VideoStreamCallback(hWnd, *lpVHdr.VIDEOHDR)
Protected cImage, *Mem
Shared WCCapture
With WCCapture
If \CB ; Manipulations - CB aufrufen falls vorhanden
If Not cImage
cImage = CreateImage(#PB_Any, \psVideoFormat\bmiHeader\biWidth, \psVideoFormat\bmiHeader\biHeight, 24)
EndIf
; Bildspeicher ermitteln
StartDrawing(ImageOutput(cImage)) : *Mem = DrawingBuffer() : StopDrawing()
CopyMemory(*lpVHdr\lpData, *Mem, *lpVHdr\dwBytesUsed) ; FrameSpeicher -> Image
\CB(cImage) ; Image bearbeiten
CopyMemory(*Mem, *lpVHdr\lpData, *lpVHdr\dwBytesUsed) ; Image -> FrameSpeicher
FreeImage(cImage)
EndIf
EndWith
EndProcedure
; ------------------------------------------------------------------------------------
; Public
; ------------------------------------------------------------------------------------
; ------------------------------------------------------------------------------------
; Hilfsfunktionen für das RawData - VideoCallback
; ------------------------------------------------------------------------------------
Macro RawData_Init(_Raw)
Protected Res.Size, *PixelData, *Pixel.RGB_24
Capture_GetResolution(@Res)
*PixelData = _Raw#\lpData
EndMacro
Macro RawData_SetPixel(x, y)
*Pixel = *PixelData + 3*((y-1)*Res\cx+(x-1))
EndMacro
Macro RawData_Height()
Res\cy
EndMacro
Macro RawData_Width()
Res\cx
EndMacro
Macro RawData_Pixel()
*Pixel
EndMacro
; ------------------------------------------------------------------------------------
; Funktionen zum erstellen und steuern der Capture - Anzeige
; ------------------------------------------------------------------------------------
; <> 0: Erfolg, 0 = Konnte nicht initialisiert werden
Procedure Capture_Init(WindowID, view_x = #Null, view_y = #Null, view_width = #Null, view_height = #Null, Resolution$ = "640x480")
Protected RtVar
Shared WCCapture
With WCCapture
\avicap32 = OpenLibrary(#PB_Any, "avicap32.dll")
If \avicap32
\hWndC = CallFunction(\avicap32, "capCreateCaptureWindowA", #Null, #WS_CHILD|#WS_VISIBLE, view_x, view_y, view_width, view_height, WindowID, 1)
If \hWndC
SendMessage_(\hWndC, #WM_CAP_DRIVER_CONNECT, 0, 0)
SendMessage_(\hWndC, #WM_CAP_SET_PREVIEW, #True, 0)
SendMessage_(\hWndC, #WM_CAP_SET_PREVIEWRATE, 2, 0)
SendMessage_(\hWndC, #WM_CAP_SET_SCALE, #True, 0)
SendMessage_(\hWndC, #WM_CAP_SET_OVERLAY, #True, 0)
SendMessage_(\hWndC, #WM_CAP_GET_VIDEOFORMAT, SizeOf(VIDEOHDR), @\psVideoFormat)
; Standard - Auflösung
Resolution$ = LCase(Resolution$)
\psVideoFormat\bmiHeader\biWidth = Val(Trim(StringField(Resolution$, 1, "x")))
\psVideoFormat\bmiHeader\biHeight = Val(Trim(StringField(Resolution$, 2, "x")))
If (Not view_width) Or (Not view_height)
\ViewData\right = \psVideoFormat\bmiHeader\biWidth
\ViewData\bottom = \psVideoFormat\bmiHeader\biHeight
EndIf
; Wir ändern hier also mal hübsch das Format, in dem wir das Bild gerne hätten.
; Standardmäßig ist es oft bei Webcams nur in 16 Bit, dann müssten wir soviel herumrechnen und könnten es uns nicht mit SetDIBits einfach machen.
; Das gesetzte Videoformat wird auch nach Programmende beibehalten, d.h. beim nächsten Start wird die Vorschau von avicap32 bereits hier oben ein 24-Bit Bild liefern!
\psVideoFormat\bmiHeader\biBitCount = 24
\psVideoFormat\bmiHeader\biCompression = #BI_RGB
\psVideoFormat\bmiHeader\biSizeImage = #False
\psVideoFormat\bmiHeader\biClrUsed = #False
\psVideoFormat\bmiHeader\biClrImportant = #False
If SendMessage_(\hWndC, #WM_CAP_SET_VIDEOFORMAT, SizeOf(VIDEOHDR), @\psVideoFormat) ; Videoformat setzen
\ViewData\top = view_y
\ViewData\bottom = view_height
\ViewData\left = view_x
\ViewData\right = view_width
\WinID = WindowID
RtVar = #True
Else
SendMessage_(\hWndC, #WM_CAP_STOP, 0, 0)
SendMessage_(\hWndC, #WM_CAP_DRIVER_DISCONNECT, 0, 0)
DestroyWindow_(\hWndC)
CloseLibrary(\avicap32)
EndIf
Else
CloseLibrary(\avicap32)
EndIf
EndIf
If Not RtVar
\avicap32 = #Null
EndIf
EndWith
ProcedureReturn RtVar
EndProcedure
; Deinitialisieren
Procedure Capture_DeInit()
Shared WCCapture
With WCCapture
If \avicap32
SendMessage_(\hWndC, #WM_CAP_STOP, 0, 0)
SendMessage_(\hWndC, #WM_CAP_DRIVER_DISCONNECT, 0, 0)
DestroyWindow_(\hWndC)
CloseLibrary(\avicap32)
\avicap32 = #Null
ProcedureReturn #True
EndIf
EndWith
EndProcedure
; Vorschau beenden/starten
Procedure Capture_Preview(Preview = #True)
Shared WCCapture
With WCCapture
If \avicap32
SendMessage_(\hWndC, #WM_CAP_SET_PREVIEW, Preview, #Null)
EndIf
EndWith
EndProcedure
; Anzeige- Fenster in der Größe ändern
Procedure Capture_Resize(view_x = #PB_Ignore, view_y = #PB_Ignore, view_width = #PB_Ignore, view_height = #PB_Ignore)
Shared WCCapture
With WCCapture
If \avicap32
If (view_y <> #PB_Ignore) : \ViewData\top = view_y : EndIf
If (view_height <> #PB_Ignore) : \ViewData\bottom = view_height : EndIf
If (view_x <> #PB_Ignore) : \ViewData\left = view_x : EndIf
If (view_width <> #PB_Ignore) : \ViewData\right = view_width : EndIf
SetWindowPos_(\hwndC, #Null, \ViewData\left, \ViewData\top, \ViewData\right, \ViewData\bottom, #Null)
EndIf
EndWith
EndProcedure
; Ermittelt Informationen über den Treiber
Procedure$ Capture_DriverInfo()
Shared WCCapture
Protected Name$, Version$, RtVar$
Name$ = Space(80)
Version$ = Space(40)
With WCCapture
If \avicap32
SendMessage_(\hWndC, #WM_CAP_DRIVER_GET_NAME, 80, @Name$)
SendMessage_(\hWndC, #WM_CAP_DRIVER_GET_VERSION, 40, @Version$)
RtVar$ = "Name: " + Name$ + Chr(13) + "Version: " + Version$
EndIf
EndWith
ProcedureReturn RtVar$
EndProcedure
; Speichert das aktuelle Frame als BMP ab
Procedure Capture_SnapShot(File$)
Shared WCCapture
With WCCapture
If \avicap32
SendMessage_(\hWndC, #WM_CAP_FILE_SAVEDIB, #Null, @File$)
EndIf
EndWith
EndProcedure
; Startet die Videoaufnahme in eine Datei
Procedure Capture_StartRecord(File$, FPS = 15, RecordAudio = #True, TimeLimit = #Null)
Shared WCCapture
With WCCapture
If \avicap32
; Aufnameoptionen und Audidaten laden
SendMessage_(\hWndC, #WM_CAP_GET_SEQUENCE_SETUP, SizeOf(CAPTUREPARAMS), @\Capture)
; Aufname einstellen
\Capture\dwRequestMicroSecPerFrame = 1000000/FPS ; FPS einstellen
\Capture\fYield = #True ; nicht-blockierend aufnehmen
\Capture\fAbortLeftMouse = #False ; kein Abbrechen mit der linken Maus
\Capture\fAbortRightMouse = #False ; kein Abbrechen mit der rechten Maus
\Capture\vKeyAbort = #Null ; kein Abbrechen mit einer Taste
\Capture\fMakeUserHitOKToCapture = #False ; Aufnehmen ohne den User zu fragen
\Capture\fCaptureAudio = RecordAudio ; Audio aufnehmen?
If TimeLimit ; Aufnahme zeitlich begrenzen?
\Capture\fLimitEnabled = #False
\Capture\wTimeLimit = TimeLimit
EndIf
If SendMessage_(\hWndC, #WM_CAP_SET_SEQUENCE_SETUP, SizeOf(CAPTUREPARAMS), @\Capture)
SendMessage_(\hWndC, #WM_CAP_FILE_SET_CAPTURE_FILE, #Null, @File$)
SendMessage_(\hWndC, #WM_CAP_SEQUENCE, #Null, #Null)
ProcedureReturn #True
EndIf
EndIf
EndWith
EndProcedure
; stop die Aufnahme
Procedure Capture_StopRecord()
Shared WCCapture
With WCCapture
If \avicap32
SendMessage_(\hWndC, #WM_CAP_STOP, #Null, #Null)
EndIf
EndWith
EndProcedure
; Ändert die Auflösung der Aufnahme.
; Das ganze passiert über ein ReInit da die "normale" Methode irgendwie nicht so ganz funktioniert ...
Procedure Capture_SetResolution(Resolution$ = "640x320")
Shared WCCapture
With WCCapture
If \avicap32
; Capture_Preview(#False)
; \psVideoFormat\bmiHeader\biWidth = Val(Trim(StringField(Resolution$, 1, "x")))
; \psVideoFormat\bmiHeader\biHeight = Val(Trim(StringField(Resolution$, 2, "x")))
; SendMessage_(\hWndC, #WM_CAP_SET_VIDEOFORMAT, SizeOf(VIDEOHDR), @\psVideoFormat)
; Capture_Preview(#True)
Capture_DeInit()
Capture_Init(\WinID, \ViewData\left, \ViewData\top, \ViewData\right, \ViewData\bottom, Resolution$)
EndIf
EndWith
EndProcedure
; Auflösung ermitteln
Procedure Capture_GetResolution(*Res.Size)
Shared WCCapture
With WCCapture
If \avicap32
*Res\cx = \psVideoFormat\bmiHeader\biWidth
*Res\cy = \psVideoFormat\bmiHeader\biHeight
EndIf
EndWith
EndProcedure
; Stellt das Aufnahme - Audioformat ein
Procedure Capture_SetAudioFormat(AudioStereo = #False, AudioSampleRate = #Capture_Audio_11kHz, AudioBitsPerSample = 8)
Shared WCCapture
With WCCapture
If \avicap32
; Aufnameoptionen und Audiodaten laden
SendMessage_(\hWndC, #WM_CAP_GET_AUDIOFORMAT, SizeOf(WAVEFORMATEX), @\CAudio)
\CAudio\wFormatTag = #WAVE_FORMAT_PCM ; Audio-Format setzen
Select AudioSampleRate ; Samplerate setzen
Case #Capture_Audio_8kHz
\CAudio\nSamplesPerSec = 8000
Case #Capture_Audio_11kHz
\CAudio\nSamplesPerSec = 11025
Case #Capture_Audio_22kHz
\CAudio\nSamplesPerSec = 22050
Case #Capture_Audio_44kHz
\CAudio\nSamplesPerSec = 44100
Default
\CAudio\nSamplesPerSec = 11025
EndSelect
If AudioStereo ; Stereo oder Mono?
\CAudio\nChannels = 2
Else
\CAudio\nChannels = 1
EndIf
If AudioBitsPerSample = 16 ; Bits Pro Sample
\CAudio\wBitsPerSample = 16
Else
\CAudio\wBitsPerSample = 8
EndIf
; Größenberechnungen
\CAudio\nBlockAlign = (\CAudio\wBitsPerSample*\CAudio\nChannels)/8
\CAudio\nAvgBytesPerSec = \CAudio\nSamplesPerSec*\CAudio\nBlockAlign
; Audio einstellen
ProcedureReturn SendMessage_(\hWndC, #WM_CAP_SET_AUDIOFORMAT, SizeOf(WAVEFORMATEX), @\CAudio)
EndIf
EndWith
EndProcedure
; Setzt das Video - Callback, wahlweise als Image oder RawData. Image-Callback funktioniert nur im
; RGB 24 Bit Modus, nicht zB. im YUY2 Modus.
Procedure Capture_SetVideoCallback(*CB, CallbackType = #Capture_Video_ImageCallback)
Protected RtVar
With WCCapture
If \avicap32
If CallbackType = #Capture_Video_ImageCallback ; (*CB._Capture_CallBack)
If \psVideoFormat\bmiHeader\biCompression = #BI_RGB
SendMessage_(\hWndC, #WM_CAP_SET_CALLBACK_FRAME, 0, @_Capture_VideoStreamCallback())
SendMessage_(\hWndC, #WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, @_Capture_VideoStreamCallback())
\CB = *CB
RtVar = #True
EndIf
Else ; (*CB.VideoStreamCallback)
SendMessage_(\hWndC, #WM_CAP_SET_CALLBACK_FRAME, 0, *CB)
SendMessage_(\hWndC, #WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, *CB)
RtVar = #True
EndIf
EndIf
EndWith
ProcedureReturn RtVar
EndProcedure
; Audio - Callback setzen
Procedure Capture_SetAudioCallback(*CB.WaveStreamCallback)
With WCCapture
If \avicap32
SendMessage_(\hWndC, #WM_CAP_SET_CALLBACK_WAVESTREAM, 0, @_Capture_VideoStreamCallback())
EndIf
EndWith
EndProcedure
; VideoFormat ändern. Achtung! Das ImageCallback funktioniert nur im RGB 24 Bit Modus.
Procedure Capture_SelectFormat()
With WCCapture
If \avicap32
If SendMessage_(\hWndC, #WM_CAP_DLG_VIDEOFORMAT, 0, 0)
SendMessage_(\hWndC, #WM_CAP_GET_VIDEOFORMAT, SizeOf(VIDEOHDR), @\psVideoFormat)
EndIf
EndIf
EndWith
EndProcedure
; VideoQuelle wählen
Procedure Capture_SelectSource()
With WCCapture
If \avicap32
SendMessage_(\hWndC, #WM_CAP_DLG_VIDEOSOURCE, 0, 0)
EndIf
EndWith
EndProcedure
; Video Einstellen
Procedure Capture_SelectOptions()
With WCCapture
If \avicap32
SendMessage_(\hWndC, #WM_CAP_DLG_VIDEODISPLAY, 0, 0)
EndIf
EndWith
EndProcedure