Search code examples
delphifiremonkeyindy

TCameraComponent and TVideoCaptureDevice do not initialize in Win32


I use the standard code to initialize TVideoCaptureDevice and start capturing.

const  M_LAUNCH_CAMERA = WM_APP + 450;
type
  TCamSF1 = class(TForm)
...
  protected
    procedure LaunchCamera(var Message: TMessage); message M_LAUNCH_CAMERA;
...
end;
...
procedure TCamSF1.LaunchCamera(var Message: TMessage);
begin
if VideoCamera = nil then
    begin
      VideoCamera := TCaptureDeviceManager.Current.DefaultVideoCaptureDevice;
      if VideoCamera <> nil then
      begin
        VideoCamera.OnSampleBufferReady := CameraReady;
        VideoCamera.StartCapture;
      end
      else
      begin
        Caption := 'Video capture devices not available.';
      end;
    end
    else
    begin
      VideoCamera.StartCapture;
    end;
end;

procedure TCamSF1.IdTCPServer1Execute(AContext: TIdContext);
var
  S: AnsiString;
  Command: TAnsiStrings;
  Msg: TMessage;
begin
  if (AContext <> nil) and (AContext.Connection.Socket.Connected) and
    (not AContext.Connection.Socket.InputBufferIsEmpty) then
    S := AContext.Connection.Socket.ReadLn;
  if S = '' then
    exit;
  Memo1.Lines.Add(S);
  Command := ParseCommandString(S, '#');
  if Command[0] = 'camresol' then
  begin
    CamShotParams := Command;
    Msg.Msg := M_LAUNCH_CAMERA;
    Dispatch(Msg);
  end;
end;

The code properly works when I dispatch a message from a button OnClick event but when the message is dispatched from TIdTCPServer OnExecute the camera does not start and Caption := 'Video capture devices not available.' is run. Moreover, after this the camera does not initialize even from the Button OnClick event.

The code also does not work in case of direct calling of

VideoCamera := TCaptureDeviceManager.Current.DefaultVideoCaptureDevice;
if VideoCamera <> nil then
  begin 
    VideoCamera.OnSampleBufferReady := CameraReady;
    VideoCamera.StartCapture;
  end;

from within Server OnExecute event. Though it works fine when run from the Button OnClick. Using of TCameraComponent cause the same problems. This issue could be reolved if camera initialization is handled in Form OnCreate event but this is not suitable as simultaneous usage of camera is not allowed by two or more applications.


Solution

  • It seems, capture device should be initialized and manipulated from the main thread. Try to wrap capture manipulating in TThread.Synchronize class procedure, smth like this:

    procedure TMyForm.IdTCPServer1Execute(AContext: TIdContext);
    ...
    begin
    ...
    TThread.Synchronize(nil,
      procedure
      begin
        DoSmthWithCamera();
      end;
    );
    ...
    end;