Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Dos cámaras en paralelo (https://www.clubdelphi.com/foros/showthread.php?t=95956)

elcigarra 09-11-2022 11:54:34

Dos cámaras en paralelo
 
Estimados, estoy intentando hacer una aplicación en DXE3, que necesita capturar video, en principio de 2 cámaras (que pueden ser la misma mostrada dos veces). Como no sé nada del tema de video, encontré en internet un código bastante simple con el que se podía capturar una cámara que funciona bien (en realidad más que capturar la cámara toma fotogramas con un timer y los muestra en un TPanel.

Para el objetivo de las dos cámaras, lo que hice fue duplicar las partes relevantes y el timer para mostrar las dos capturas, pero lo que me pasa es que solo se ve una y la otra se muestra un plano verde. Les pongo el código a ver qué opinan.

Código:

unit TwoCamsMain;
interface
uses
  Windows,Messages,SysUtils,Classes,Graphics,Controls,Forms,Dialogs,ExtCtrls,
  StdCtrls,Menus, Buttons;
const
  WM_CAP_START                  = WM_USER;
  WM_CAP_STOP                  = WM_CAP_START+68;
  WM_CAP_DRIVER_CONNECT        = WM_CAP_START+10;
  WM_CAP_DRIVER_DISCONNECT      = WM_CAP_START+11;
  WM_CAP_SAVEDIB                = WM_CAP_START+25;
  WM_CAP_GRAB_FRAME            = WM_CAP_START+60;
  WM_CAP_SEQUENCE              = WM_CAP_START+62;
  WM_CAP_FILE_SET_CAPTURE_FILEA = WM_CAP_START+20;
type
  TForm1 = class(TForm)
    Timer1: TTimer;
    Panel1: TPanel;
    Panel2: TPanel;
    Timer2: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Timer1Timer(Sender: TObject);
    procedure Timer2Timer(Sender: TObject);
  private
    hWndC:THandle;
    hWndC_B:THandle;
    FPS:integer;
    procedure ConectarDrive;
    procedure CreaHandle;
    procedure DesconectarDrive;
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;


  function capCreateCaptureWindowA(lpszWindowName : PCHAR;
                                dwStyle : longint;
                                x : integer;
                                y : integer;
                                nWidth : integer;
                                nHeight : integer;
                                ParentWin  : HWND;
                                nId : integer): HWND;
                                STDCALL EXTERNAL 'AVICAP32.DLL';

implementation
{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  FPS:=24;
  Timer1.Interval:=1000 div FPS;
  Timer2.Interval:=1000 div FPS;
  hWndC:=0;
  hWndC_B:=0;
  CreaHandle;
  ConectarDrive;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Application.ProcessMessages;
  if hWndC<>0 then begin
      SendMessage(hWndC, WM_CAP_GRAB_FRAME, 0, 0);
      Timer1.Enabled:=True;
  end;
end;

procedure TForm1.Timer2Timer(Sender: TObject);
begin
//  Application.ProcessMessages;
  if hWndC_B<>0 then begin
      SendMessage(hWndC_B, WM_CAP_GRAB_FRAME, 0, 0);
      Timer2.Enabled:=True;
  end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  DesconectarDrive;
end;

procedure TForm1.CreaHandle;
begin
    try
        hWndC:=capCreateCaptureWindowA(' Video',
                                      WS_CHILD or WS_VISIBLE,
                                      0,
                                      0,
                                      Width,
                                      Height,
                                      Panel1.Handle,
                                      0);
        hWndC_B:=capCreateCaptureWindowA(' Video',
                                      WS_CHILD or WS_VISIBLE,
                                      0,
                                      0,
                                      Width,
                                      Height,
                                      Panel2.Handle,
                                      0);
    except
          ShowMessage('error en handle');
    end;
end;
procedure TForm1.ConectarDrive;
begin
    try
        if hWndC<>0 then begin
          SendMessage(hWndC, WM_CAP_DRIVER_CONNECT, 0, 0);
        end;
        if hWndC_B<>0 then begin
          SendMessage(hWndC_B, WM_CAP_DRIVER_CONNECT, 0, 0);
        end;
        Timer1.Enabled:=True;
        Timer2.Enabled:=True;
    except
          ShowMessage('error al desconectar'); // error mesg
    end;
end;
procedure TForm1.DesconectarDrive; // Disconnect
begin
  try
      if hWndC<>0 then begin
        SendMessage(hWndC, WM_CAP_DRIVER_DISCONNECT, 0, 0);
        hWndC:=0;
        SendMessage(hWndC_B, WM_CAP_DRIVER_DISCONNECT, 0, 0);
        hWndC_B:=0;
      end;
  except
      ShowMessage('error al desconectar'); // error message
  end;
end;
end.


Casimiro Notevi 09-11-2022 13:20:35

¿Cuál es la pregunta o la duda?

Neftali [Germán.Estévez] 09-11-2022 15:36:37

¿Esta cadena ' Video' de dónde sale?

Código Delphi [-]
hWndC:=capCreateCaptureWindowA(' Video', ...

¿Qué valen los 2 handles (hWndC, hWndC_B) una vez capturadas?

elcigarra 09-11-2022 22:51:37

Cita:

Empezado por Casimiro Notevi (Mensaje 549076)
¿Cuál es la pregunta o la duda?

Que, como dije, no funciona para las dos cámaras, solo se ve una y la otra sale verde. La pregunta es si alguien sabe por qué.

Cita:

Empezado por Neftali [Germán.Estévez] (Mensaje 549085)
¿Esta cadena ' Video' de dónde sale?

Esa cadena 'Video' es un nombre cualquiera para la ventana de captura de la función esa capCreateCaptureWindowA pero aclaro que no sé mucho del tema (igual decir 'no se mucho' es casi soberbio, mas bien no se nada).

Cita:

Empezado por Neftali [Germán.Estévez] (Mensaje 549085)
¿Qué valen los 2 handles (hWndC, hWndC_B) una vez capturadas?

No entiendo bien tu pregunta, seguramente debido a mi ignorancia en el tema. ¿Esto handles no son los lugares donde se volcara las capturas de los dos videos?. Según entiendo cada video se muestra en el handle de un TPanel. No sé por qué si el código es igual solo puede mostrarse una.

Pero igualmente, si alguien conoce otra forma de acceder a dos cámaras de video en paralelo y tiene de donde aprender agradezco la referencia. Yo solo he encontrado explicaciones para una cámara sola. Gracias.

Neftali [Germán.Estévez] 10-11-2022 09:38:10

Cita:

Empezado por elcigarra (Mensaje 549095)
¿Esto handles no son los lugares donde se volcara las capturas de los dos videos?. Según entiendo cada video se muestra en el handle de un TPanel. No sé por qué si el código es igual solo puede mostrarse una.

Los handles son los identificadores de ventana. Se almacenan como un integer.
Una vez que has hecho la llamada a la función los 2 handles deben ser diferentes y positivos, por eso te preguntaba. Si hay algun problema con esa captura, o serán los 2 iguales o alguno será negativo o cero (imagino).

Lo que veo extraño es que haces las 2 llamadas a la función de forma igual (parámetros) cambiando simplemente el panel para recibir las capturas. Con esas 2 llamadas no veo forma de que tu programa Delphi sepa discernir entre las 2 cámaras que tienes instaladas.

NOTA: Sólo para probar, prueba a pasar un valor distinto en el primer parámetro cuando haces la conexion y/o la captura:
Código Delphi [-]
...
SendMessage(hWndC, WM_CAP_DRIVER_CONNECT, 0, 0);
SendMessage(hWndC, WM_CAP_DRIVER_CONNECT, 1, 0);
...
SendMessage(hWndC_B, WM_CAP_GRAB_FRAME, 0, 0);
SendMessage(hWndC_B, WM_CAP_GRAB_FRAME, 1, 0);

elcigarra 10-11-2022 12:41:57

Gracias chicos. Probé cambiar ese parámetro, cambiar el último parámetro (el identificador de windows) en capCreateCaptureWindowA, cambiar algunos, cambiarlos todos, pero siempre obtengo el mismo resultado, solo una cámara funciona.

Aclaro que el código que puse arriba está completo y aislado porque es lo único que me resta resolver, es un form con dos TPanel y dos TTimer . Lo digo porque capaz que algún experto en procesos de windows de tantos que hay aquí aprovecha un rato de ocio activo, lo puede probar y dejarlo funcionando. Harían feliz a un pobre programador aficcionado ya entrado en años :).

Neftali [Germán.Estévez] 10-11-2022 13:43:51

Cita:

Empezado por elcigarra (Mensaje 549102)
Gracias chicos. Probé cambiar ese parámetro, cambiar el último parámetro (el identificador de windows) en capCreateCaptureWindowA, cambiar algunos, cambiarlos todos, pero siempre obtengo el mismo resultado, solo una cámara funciona..

Yo me refería a cambiar los parámetros cuando llamas al SendMessage.
Revisa los valores en rojo (de más arriba).

Aqui:
https://learn.microsoft.com/en-us/wi...driver-connect

Habla de esto:
Index of the capture driver. The index can range from 0 through 9.

elcigarra 14-11-2022 12:24:46

Thread-safe postmessage
 
Sigo con mi asunto de las dos cámaras en paralelo. Para empezar digo que estoy usando la librería VFrames de GRBLize de aquí:
https://github.com/MakeMagazinDE/GRB...er/VFrames.pas

Lo que me pasa es que si yo llamo a ambas cámaras desde el hilo principal de la aplicación funciona correctamente (veo las dos cámaras) pero el programa es una carreta y refrescan cada 5 segundos. Lo que se me ocurrió es meter cada llamada en un hilo. El problema es que haciéndolo así cuando seteo la fuente de la segunda cámara me cambia las dos y me muestran la misma imagen (de la segunda cámara). Me da la sensación que esto es porque esta biblioteca VFrames no es Thread safe. En mi ignorancia (hago agua en threads y océanos en procesos de windows, mi excusa es que programo como hobby nada más :cool:) me da la sensación que el problema está en la linea
Código:

PostMessage(fMessageHWND, fMsgNewFrame, Size, integer(fImagePtr[i]));
Hay un comentario en esta linea de código
// This routine is called by the video software and therefore runs within their thread.
// Posting a message to our own HWND will transport the information to the main thread.


No me queda claro por qué si fMessageHWND para cada hilo se carga en el constructor, como el segundo hilo puede cambiar el identificador del primero.


La franja horaria es GMT +2. Ahora son las 14:19:36.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi