How to capture and save to file from webcam using DSPack and Delphi 5

3.3k views Asked by At

right now I'm trying to make a program using Delphi 5 to take a photo from webcam. I'm using delphi 5 and DSPack 2.3.1 because many people suggest it, and yes this is my first time programming multimedia with delphi.

I've been able to list and add camera that connect to my computer dynamically. I'm also able to display what the webcam "see", opening a video and capture it. But now I can't capture a picture from the webcam.

I have a TImage which I named "Image", to check the picture is captured or not. When I use my code to open a video and capture it, it displayed in the TImage. But when I try to capture a webcam, it's just blank and not capturing anything. The file I saved also blank.

Could someone check which part of my code goes wrong? Thanks before...

here's part of my code

var SysDev: TSysDevEnum;
    FotoBitmap: TBitmap;

implementation

{$R *.DFM}

procedure Form1.FormCreate(Sender: TObject);
var
  i: integer;
  Device: TMenuItem;
begin
  SysDev:= TSysDevEnum.Create(CLSID_VideoInputDeviceCategory);
  if SysDev.CountFilters > 0 then
    for i := 0 to SysDev.CountFilters - 1 do
    begin
      Device := TMenuItem.Create(Devices);
      Device.Caption := SysDev.Filters[i].FriendlyName;
      Device.Tag := i;
      Device.OnClick := OnSelectDevice;
      Devices.Add(Device);
    end;
end;

procedure Form1.FormCloseQuery(Sender: TObject;
  var CanClose: Boolean);
begin
  SysDev.Free;
  FilterGraph.ClearGraph;
  FilterGraph.Active := false;
end;

procedureForm1.OnSelectDevice(sender: TObject);
var
  CaptureGraph: ICaptureGraphBuilder2;
  SourceFilter, DestFilter: IBaseFilter;
begin
  FilterGraph.ClearGraph;
  FilterGraph.Active := false;

  Filter.BaseFilter.Moniker := SysDev.GetMoniker(TMenuItem(Sender).tag);
  Filter.FilterGraph := FilterGraph;

  FilterGraph.Active := true;

  FilterGraph.QueryInterface(ICaptureGraphBuilder2, CaptureGraph);

  Filter.QueryInterface(IBaseFilter, SourceFilter);

  VideoWindow.QueryInterface(IBaseFilter, DestFilter);

  if Filter.BaseFilter.DataLength > 0 then
    CaptureGraph.RenderStream(nil, nil, SourceFilter, nil, DestFilter);

  FilterGraph.Play;
  CaptureGraph := nil;
  SourceFilter := nil;
  DestFilter   := nil;
end;

procedure Form1.SnapshotClick(Sender: TObject);
var dir : String;
begin
  if edt_nama_foto.Text <> '' then begin
    dir := ExtractFilePath(Application.ExeName);
    FotoBitmap := TBitmap.Create;

    try
      SampleGrabber.GetBitmap(FotoBitmap);
      SampleGrabber.GetBitmap(Image.Picture.Bitmap);
      showmessage(dir + 'Image\Foto\' + edt_nama_foto.Text + '.bmp');
      FotoBitmap.SaveToFile(dir + 'Image\Foto\' + edt_nama_foto.Text + '.bmp');
    finally
      FotoBitmap.Free;
    end;
  end;
end;

procedure Form1.btn_batalClick(Sender: TObject);
begin
  modalresult:=mrCancel;
end;

procedure Form1.btn_simpanClick(Sender: TObject);
begin
  If CheckbeforeOK then
  begin
    ModalResult :=mrOK;
  end else begin
    ModalResult := mrNone;
  end;
end;

function Form1.CheckbeforeOK:Boolean;
var flag:boolean;
    MasterDataSet:TQuery;
begin
  Flag:=True;

  if flag and not(checkedit(nil, nil, edt_nama_foto, edt_nama_foto.Text, 'Nama Foto'))
  then begin
    flag := False;
  end else begin
    Snapshot.Click;
  end;
  Result := flag;
end;

procedure Form1.SampleGrabberBuffer(sender: TObject;
  SampleTime: Double; pBuffer: Pointer; BufferLen: Integer);
begin
  Image.Picture.Bitmap.Canvas.Lock;
  try
    SampleGrabber.GetBitmap(Image.Picture.Bitmap, pBuffer, BufferLen);
  finally
    Image.Picture.Bitmap.Canvas.UnLock;
  end;
end;

end.
1

There are 1 answers

0
Roman Ryltsov On

The object which "transfers" video frame into image object is SampleGrabber:

SampleGrabber.GetBitmap(Image.Picture.Bitmap, pBuffer, BufferLen);

However it needs to be inserted in to filter graph when you build it, and you are apparently not doing it in your OnSelectDevice: there is no mention of SampleGrabber there at all. You need to include it into RenderStream call or otherwise get it inserted there so that video is streamed through it and your callback is called copying data into TImage.