Einzelnen Beitrag anzeigen

dragi

Registriert seit: 22. Jul 2003
198 Beiträge
 
Delphi 2005 Personal
 
#5

Re: Rückumwandlung eines gegrabten Frames (Webcam) in Bitmap

  Alt 2. Dez 2005, 21:36
Hallo,

ich habe den oben abgebildeten Code mal ausprobiert, bekomme aber eine Exception (Lesen von Adresse 000000) bei der Methode
Code:
  SetBitmapBits(FBitmap.Handle,PicWidth*PicHeight*SizeOf(DWord),@Buf1);
in der Funktion FrameCallbackFunction. Kann mir vielleicht jemand sagen wo bei mir der Fehler ist?
Hier der Versuch das oben abgebildete in eine Unit zu packen:

Code:
unit frm_MTMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, YUVConverts, ExtCtrls;

const
  WM_CAP_DRIVER_CONNECT          = WM_USER + 10;
  WM_CAP_EDIT_COPY               = WM_USER + 30;
  WM_CAP_SET_PREVIEW             = WM_USER + 50;
  WM_CAP_SET_OVERLAY             = WM_USER + 51;
  WM_CAP_SET_PREVIEWRATE         = WM_USER + 52;
  WM_CAP_GRAB_FRAME_NOSTOP       = WM_User + 61;
  WM_CAP_SET_CALLBACK_FRAME      = WM_User + 5;
  WM_CAP_DLG_VIDEOFORMAT         = WM_USER+41;  //Formatauswahl
  WM_CAP_DLG_VIDEOSOURCE         = WM_USER+42;  //Einstellungen
  WM_CAP_DLG_VIDEOCOMPRESSION    = WM_USER+46;  //Kompression
  PicWidth                       = 640;
  PicHeight                      = 480;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
  public
  end;

type
  DWordDim = array[1..PicWidth] of DWord;

Type
  TVIDEOHDR = record // lpVHdr, aus dem INet herausgefischt
  lpData : Pointer; // address of video buffer
  dwBufferLength : DWord; // size, in bytes, of the Data buffer
  dwBytesUsed : DWord; // see below
  dwTimeCaptured : DWord; // see below
  dwUser : DWord; // user-specific data
  dwFlags : DWord; // see below
  dwReserved1, dwReserved2, dwReserved3 : DWord; // reserved; do not use
end;
  TVIDEOHDRPtr = ^TVideoHDR;

var
  Form1: TForm1;
  VHandle : THandle;
  GrabFrameFlag : Boolean;
  Buf1,Buf2 : array[1..PicHeight] of DWordDim;
  FBitmap : TBitmap;

implementation

{$R *.dfm}

function capCreateCaptureWindow(lpszWindowName: LPCSTR;
    dwStyle: DWORD;
    x, y,
    nWidth,
    nHeight: integer;
    hwndParent: HWND;
    nID: integer): HWND; stdcall;
    external 'AVICAP32.DLL' name 'capCreateCaptureWindowA';

function FrameCallbackFunction(AHandle : hWnd; VIDEOHDR : TVideoHDRPtr): bool; stdcall;
var I : integer;
  AColor : array[1..4] of byte;
begin
  result := true;
  // da diese Callback-Funktion sonst bei jedem Preview-Frame ganz durchlaufen werden würde:
  if GrabFrameFlag = false then exit;
  GrabFrameFlag := false;
  // dekomprimieren der Frame-Rohdaten
  { TVideoCodec = (vcUnknown, vcRGB, vcYUY2, vcUYVY, vcBTYUV, vcYVU9, vcYUV12, vcY8, vcY211); }
  ConvertCodecToRGB(vcYUV12,VideoHDR^.lpData,@Buf2,PicWidth,PicHeight);
  // da zu einem bottom-up-bitmap dekomprimiert wird, drehe ich die Daten nochmal rum
  for I := 1 to PicHeight do Buf1[I] := Buf2[PicHeight -(I-1)];
  // laden der fertigen Pixel-Daten nach FBitmap
  SetBitmapBits(FBitmap.Handle,PicWidth*PicHeight*SizeOf(DWord),@Buf1);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  VHandle := capCreateCaptureWindow('Video',ws_child+ws_visible, 0, 0,
  PicWidth, PicHeight, Panel1.Handle, 1);
  SendMessage(VHandle, WM_CAP_DRIVER_CONNECT, 0, 0);
  SendMessage(VHandle, WM_CAP_SET_PREVIEWRATE, 15, 0);
  sendMessage(VHandle, WM_CAP_SET_OVERLAY, 1, 0);
  SendMessage(VHandle, wm_cap_set_preview, 1, 0);
  SendMessage(VHandle, WM_CAP_SET_CALLBACK_FRAME, 0, integer(@FrameCallbackFunction));
  SendMessage(VHandle,WM_CAP_DLG_VIDEOFORMAT,1,0);
  FBitmap := TBitmap.Create;
  FBitmap.Width := PicWidth;
  FBitmap.Height := PicHeight;
  FBitmap.PixelFormat := pf32Bit;
  GrabFrameFlag := false;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FBitmap.free;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  GrabFrameFlag := true;
  SendMessage(VHandle, WM_CAP_GRAB_FRAME_NOSTOP, 1, 0); // für die Hintergrundlaufbarkeit
end;

end.
Delphi 3 Professional @home
Delphi 2005 PE @home
Delphi 2005 Enterprise @work
  Mit Zitat antworten Zitat