Autor |
Beitrag |
mtin
Beiträge: 177
Win XP SP2
BDS2006 Enterprise
|
Verfasst: Di 21.03.06 19:28
also, ich hab jetzt immernoch Probleme mit meiner Webcam
nachdem jetzt normal alles klappt, würde ich das ganze gerne in eine eigene Klasse TWebcam packen...
das funktioniert soweit auch ganz gut, nur müsste ich die Callback-funktion ja mit reinnehmen, da sie auf Variablen der Klasse zugreift!
nochmal zum Verständnis: Die Callback-Funktion sieht so aus: Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| function OnFrame(hCapWnd: HWND; lpVHDR: PVideoHdr): DWord; stdcall; begin Result:=1; SendMessage(CapHandle, WM_CAP_GET_VIDEOFORMAT, SizeOf(BitmapInfo), Integer(@BitmapInfo));
src:=lpVHdr^.lpData; dest:=Frame.ScanLine[0];
case bitmapinfo.bmiHeader.biCompression of UYVY: UYVYtoARGB(src, dest, w, h); YUY2: YUY2toARGB(src, dest, w, h); I420: I420toARGB(src, dest, w, h); end;
Frame.Changed; end; | Und der Webcam sage ich so, wie sie die Callback-Funktion findet:
Delphi-Quelltext 1:
| SendMessage(CapHandle, WM_CAP_SET_CALLBACK_FRAME, 0, Integer(@OnFrame)); |
So funktioniert alles außer, dass ich alle benötigte Variablen nicht in die TWebcam reinschreiben kann sondern Global machen muss. Damit genau das funktioniert, hab ich mir gedacht, ich schreib einfach sowohl vor die Funktion an sich als auch in dieser Zeile ein TWebcam.OnFrame:
Delphi-Quelltext 1:
| SendMessage(CapHandle, WM_CAP_SET_CALLBACK_FRAME, 0, Integer(@TWebcam.OnFrame)); |
(und dann natürlich noch in der Klasse TWebcam die Funktion deklarieren)
allerdings klappt dann irgendwas nicht mehr, bei der Zeile Delphi-Quelltext 1: 2:
| src:=lpVHdr^.lpData; dest:=Frame.ScanLine[0]; | kommt irgendeine exception...ich weiß auch nicht genau was da schiefläuft...
sobald ich dann wieder das aus der Klasse rausnehme und einfach global mache klappt wieder alles...
hatt irgendjemand davon ne Ahnung?
|
|
digi_c
Beiträge: 1905
W98, XP
D7 PE, Lazarus, WinAVR
|
Verfasst: Di 21.03.06 22:20
Was für eine Exception den? In Messageboxen kann man mit STRG+C den Text kopieren.
Vermutlich greifst du auf Speicher zu der eigentlich nicht dir gehört, kann er denn lpVHdr^ dereferenzieren?
|
|
mtin
Beiträge: 177
Win XP SP2
BDS2006 Enterprise
|
Verfasst: Di 21.03.06 22:54
First chance exception at $7C81EB33. Exception class EAccessViolation with message 'Access violation at address 0046DE0C in module 'TWebcam.exe'. Read of address 00DD0944'. Process TWebcam.exe (1568)hm, du hattest Recht, lpVHdr^ zeigt auf nil...also nichts...
hast du eine Ahnung wieso das immer auftritt wenn ich das in die TWebcam-Klasse mit aufnehme?
Ich mach hier einfach mal meine gesamte Unit rein...
wenn du die Graphics32-Komponenten hast könntest du das ja vielleicht mal ausprobieren?
einfach in einem neuen Projekt die Unit einbinden und dann
Delphi-Quelltext 1: 2: 3: 4: 5:
| var cam:TWebcam;
cam:=TWebcam.Create(Form1.Handle);
Image321.Bitmap:=cam.Frame; |
hier ist sie:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161:
| unit webcamdriver;
interface
uses GR32, UConvert, Windows, Messages, ExtCtrls, SysUtils;
function capCreateCaptureWindow(lpszWindowName : LPCSTR; dwStyle : DWORD; x, y : Integer; nWidth : Integer; nHeight : Integer; hwndParent : HWND; nID : Integer ): HWND; stdcall; external 'AVICAP32.DLL' name 'capCreateCaptureWindowA';
type PVIDEOHDR = ^TVIDEOHDR; TVIDEOHDR = packed record lpData : PBYTE; dwBufferLength : DWORD; dwBytesUsed : DWORD; dwTimeCaptured : DWORD; dwUser : DWORD; dwFlags : DWORD; dwReserved : array[0..3] of DWORD; end;
type TWebcam = class private var CapHandle: HWND; w,h: Integer; const WM_CAP_SET_CALLBACK_FRAME = (WM_USER + 5); WM_CAP_DRIVER_CONNECT = (WM_USER + 10); WM_CAP_DRIVER_DISCONNECT = (WM_USER + 11); WM_CAP_EDIT_COPY = (WM_USER + 30); WM_CAP_DLG_VIDEOFORMAT = (WM_USER + 41); WM_CAP_DLG_VIDEOSOURCE = (WM_USER + 42); WM_CAP_DLG_VIDEODISPLAY = (WM_USER + 43); WM_CAP_GET_VIDEOFORMAT = (WM_USER + 44); WM_CAP_SET_VIDEOFORMAT = (WM_USER + 45); WM_CAP_DLG_VIDEOCOMPRESSION = (WM_USER + 46); WM_CAP_SET_PREVIEW = (WM_USER + 50); WM_CAP_SET_OVERLAY = (WM_USER + 51); WM_CAP_SET_PREVIEWRATE = (WM_USER + 52); WM_CAP_SET_SCALE = (WM_USER + 53); procedure bildgroesse_anpassen; public var resolution,bit,compression: string; Frame: TBitmap32; constructor create(FormHandle:HWND); function OnFrame(hCapWnd: HWND; lpVHDR: PVideoHdr): DWord; stdcall; procedure DLG_VideoSource; procedure DLG_VideoFormat; procedure DLG_VideoCompression; end;
implementation
function TWebcam.OnFrame(hCapWnd: HWND; lpVHDR: PVideoHdr): DWord; stdcall; var BitmapInfo: TBitmapInfo; src, dest: Pointer; begin Result:=1; FillChar(BitmapInfo, SizeOf(BitmapInfo), 0); SendMessage(CapHandle, WM_CAP_GET_VIDEOFORMAT, SizeOf(BitmapInfo), Integer(@BitmapInfo));
src:=lpVHdr^.lpData; dest:=Frame.ScanLine[0];
case bitmapinfo.bmiHeader.biCompression of BI_RGB: case bitmapinfo.bmiHeader.biBitCount of 16: Conv16To32(src, dest, w, h); 24: Conv24To32(src, dest, w, h); 32: Move(src^, dest^, w*h*4); end; UYVY: UYVYtoARGB(src, dest, w, h); YUY2: YUY2toARGB(src, dest, w, h); I420: I420toARGB(src, dest, w, h); end;
Frame.Changed; end;
constructor TWebcam.create(FormHandle:HWND); begin inherited Create; CapHandle:=capCreateCaptureWindow('Video', ws_child + ws_visible, 0, 0, 1, 1, FormHandle, 1);
SendMessage(CapHandle, WM_CAP_DRIVER_CONNECT, 0, 0); SendMessage(CapHandle, WM_CAP_SET_PREVIEWRATE,1, 0); sendMessage(Caphandle, WM_CAP_SET_OVERLAY, 1, 0); SendMessage(CapHandle, WM_CAP_SET_CALLBACK_FRAME, 0, Integer(@TWebcam.OnFrame));
Frame:=TBitmap32.Create; bildgroesse_anpassen;
end;
procedure TWebcam.bildgroesse_anpassen; var BitmapInfo: TBitmapInfo; begin SendMessage(CapHandle, WM_CAP_GET_VIDEOFORMAT, SizeOf(BitmapInfo), Integer(@BitmapInfo)); w:=bitmapinfo.bmiHeader.biWidth; h:=bitmapinfo.bmiHeader.biHeight; Frame.SetSize(w, h); resolution:=IntToStr(w)+'x'+IntToStr(h); bit:=IntToStr(bitmapinfo.bmiHeader.biBitCount)+'bit'; compression:=GETFOURCC(bitmapinfo.bmiHeader.biCompression); end;
procedure TWebcam.DLG_VideoFormat; begin sendMessage(CapHandle, WM_CAP_DLG_VIDEOFORMAT, 1, 0); bildgroesse_anpassen; end; procedure TWebcam.DLG_VideoSource; begin sendMessage(CapHandle, WM_CAP_DLG_VIDEOSOURCE, 1, 0); bildgroesse_anpassen; end;
procedure TWebcam.DLG_VideoCompression; begin sendMessage(CapHandle, WM_CAP_DLG_VIDEOCOMPRESSION, 1, 0); bildgroesse_anpassen; end;
end. |
ich häng mal auch gleich ein Beispielprojekt an...da sind alle jetzigen funktionen der Unit drin...
EDIT: hab vergessen das du auch noch die UConvert.pas brauchst...die ist in der angehängten Datei!
Einloggen, um Attachments anzusehen!
|
|
digi_c
Beiträge: 1905
W98, XP
D7 PE, Lazarus, WinAVR
|
Verfasst: Mi 22.03.06 09:06
Sry aber ich bearbeite gerade mein Projekt für meine Prüfung und habe daher recht wenig Zeit. Ich habe auch keine Erfahrung auf dem Gebiet. Ich denke du könntest das der Community veranschaulichen, wenn du mal komplett die Klasse vorher und hinterher postest. Vermutlich hängt das mit dem StdCall oder ähnlichen Dingen zusammen.
Wäre es nicht einfacher die Callback so zu lassen aber darin die eigentliche Verarbeitung durch eine Klassenmethode anzustoßen? IMHO wäre das o.k. und verständlich.
|
|
mtin
Beiträge: 177
Win XP SP2
BDS2006 Enterprise
|
Verfasst: Mi 22.03.06 17:26
mhm, gut ich überarbeite die nochma und stell das wichtigste dann rein...aber wie meinst du das?
Wie soll ich die eigentliche Verarbeitung in eine Klassenmethode auslagern?
Die kann ich ja nicht aufrufen...also sowas wie hier im nachfolgenden geht natürlich nicht Delphi-Quelltext 1: 2: 3: 4: 5:
| function OnFrame(hCapWnd: HWND; lpVHDR: PVideoHdr): DWord; stdcall; begin Result:=1; TWebcam.AfterFrame(lpVHDR); end; |
gut, hier ist jetzt das wichtigste (wirklich nur das was die Callback-Funktion betrifft, so funktioniert das ganze sicher nicht
Die Deklaration dieses "TVIDEOHDR" Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| unit webcamdriver;
interface
uses GR32, UConvert, Windows, Messages, ExtCtrls, SysUtils;
type PVIDEOHDR = ^TVIDEOHDR; TVIDEOHDR = packed record lpData : PBYTE; dwBufferLength : DWORD; dwBytesUsed : DWORD; dwTimeCaptured : DWORD; dwUser : DWORD; dwFlags : DWORD; dwReserved : array[0..3] of DWORD; end; |
und jetzt die beiden Teile, einfach nur die Callback-Funktion mit in die Klasse TWebcam aufgenommen oder eben nicht, wäre aber wegen der Variablen sehr viel schöner!
AUßERHALB der Klasse 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32:
| var CapHandle: HWND; const WM_CAP_SET_CALLBACK_FRAME = (WM_USER + 5);
var Frame: TBitmap32;
type TWebcam = class private
public constructor create(FormHandle:HWND); end;
implementation
function OnFrame(hCapWnd: HWND; lpVHDR: PVideoHdr): DWord; stdcall; begin
----> lpVHDR enthält die Videodaten (alles funktioniert perfekt) end;
constructor TWebcam.create(FormHandle:HWND); begin inherited Create; SendMessage(CapHandle, WM_CAP_SET_CALLBACK_FRAME, 0, Integer(@OnFrame)); end; | INNERHALB der Klasse 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34:
| type TWebcam = class private var CapHandle: HWND; const WM_CAP_SET_CALLBACK_FRAME = (WM_USER + 5); var Frame: TBitmap32;
public constructor create(FormHandle:HWND); function OnFrame(hCapWnd: HWND; lpVHDR: PVideoHdr): DWord; stdcall;
end;
implementation
function TWebcam.OnFrame(hCapWnd: HWND; lpVHDR: PVideoHdr): DWord; stdcall; begin
----> lpVHDR ist "NIL" (exceptions über exceptions^^) end;
constructor TWebcam.create(FormHandle:HWND); begin inherited Create; SendMessage(CapHandle, WM_CAP_SET_CALLBACK_FRAME, 0, Integer(@TWebcam.OnFrame)); end; | (Veränderungen sind hervorgehoben)
ahja.. ich hab keine Ahnung was das StdCall überhaupt bedeutet, ich les es jetzt mal nach aber vielleicht kann mir trotzdem jemand helfen
|
|
mtin
Beiträge: 177
Win XP SP2
BDS2006 Enterprise
|
Verfasst: Sa 25.03.06 15:55
kennt sich da denn keiner aus?
oder beschreib ich das zu schlecht?
brauche H I L F E!!
|
|
digi_c
Beiträge: 1905
W98, XP
D7 PE, Lazarus, WinAVR
|
Verfasst: Di 28.03.06 15:12
Callbacks zu machen ohne wissen über DLLs,Speichermanagement,... kann sehr langwierig werden, weil einen Delphi da nichtmehr unterstützen kann da die Daten auch aus anderen Sprachen,Formaten,... kommen können.
STDCll ist eine Aufrufkonvention und gibt An in welcher Reihenfolge Parameter erwartet werden.
Ja so wie du das im ersten Source gemacht hast meinte ich das eine Funktion außerhalb der Klasse, die die Klassenmethode anstößt.
Hast du auch deine Methode als external; gekennzeichnet? Ansonsten sind die von außen nicht verfügbar!
Ich habe wie gesagt leider nicht das Wissen noch die Zeit noch die Möglichkeiten das detailiert nachzutesten, sry
|
|
|