Effettuare una ripresa video mediante una WebCam con il Componente gb.media

Da Gambas-it.org - Wikipedia.
Vai alla navigazione Vai alla ricerca

Il Componente gb.media, utilizzando particolari plugin di GStreamer, consente di effettuare una ripresa video mediante una WebCam.


Uso della Classe MediaPlayer

Questa modalità standard prevede l'utilizzo della Classe MediaPlayer.

Esempio in un'applicazione grafica

Mostriamo di seguito un esempio essenziale con un'applicazione grafica. Il video sarà mostrato all'interno di una DrawingArea posta sul Form principale.

Private DrawingArea1 As DrawingArea
Private mp As MediaPlayer


Public Sub Form_Open()

  With DrawingArea1 = New DrawingArea(Me)
    .X = 10
    .Y = 10
    .W = 640
    .H = 480
  End With

End


Public Sub ToggleButton1_Click()

 If ToggleButton1.Value Then 
   With mp = New MediaPlayer
' Se il lettore multimediale sta già riproducendo qualcosa, lo ferma prima di iniziare una nuova riproduzione ed esce dalla routine:
     If .State = Media.Playing Then
       .Stop
       .Close
       Return 
     Endif
' Imposta la sorgente video: in questo caso è un dispositivo video Linux (Video4Linux2), tipicamente una webcam collegata al sistema, accessibile tramite /dev/video0:
     .URL = "v4l2:///dev/video0"
' ...ma anche ad esempio così:
'    .URL = "v4l2:///dev/v4l/by-id/usb-Generic_Integrated_Camera_0001-video-index0"

' Specifica che il video deve essere visualizzato nella "DrawingArea": [Nota 1]
     .SetWindow(DrawingArea1)
' Avvia la riproduzione del flusso video:
     .Play()
   End With
 Else
' Cliccando nuovamente sul "ToggleButton", arresta la ripresa video:
   mp.Stop
   mp.Close
   DrawingArea1.Clear
 Endif 

End

Modificare la dimensione del video con lo spostamento del mouse

In questo esempio, dopo aver cliccato su un punto del video, l'utente potrà modificare arbitrariamente la dimensione del video spostando il mouse, mentre si mantiene il suo puntatore cliccato sul video.
Come Controllo di base del video useremo una DrawingArea.

Private DrawingArea1 As DrawingArea
Private mp As MediaPlayer
Private ms As New Short[2]


Public Sub Form_Open()

 With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
   .X = 10
   .Y = 10
   .W = 640
   .H = 480
 End With

End

Public Sub ToggleButton1_Click()

 If ToggleButton1.Value Then 
   With mp = New MediaPlayer
' Se il lettore multimediale sta già riproducendo qualcosa, lo ferma prima di iniziare una nuova riproduzione ed esce dalla routine:
     If .State = Media.Playing Then
       .Stop
       .Close
       Return 
     Endif
' Imposta la sorgente video: in questo caso è un dispositivo video Linux (Video4Linux2), tipicamente una webcam collegata al sistema, accessibile tramite /dev/video0:
     .URL = "v4l2:///dev/video0"
' ...ma anche ad esempio così:
'    .URL = "v4l2:///dev/v4l/by-id/usb-Generic_Integrated_Camera_0001-video-index0"
' Specifica che il video deve essere visualizzato nella "DrawingArea": [Nota 1]
     .SetWindow(DrawingArea1)
' Avvia la riproduzione del flusso video:
     .Play()
   End With
 Else
' Cliccando nuovamente sul "ToggleButton", arresta la ripresa video:
   mp.Stop
   mp.Close
   DrawingArea1.Clear
 Endif 

End


Public Sub DrawingArea1_MouseMove()

 ms[0] = Mouse.X
 ms[1] = Mouse.Y

 DrawingArea1.Refresh

End 


Public Sub DrawingArea1_draw()

 If Not Object.IsValid(mp) Then Return 

 Dim im As Image = mp.Video.Image.Stretch(ms[0], ms[1])

 Paint.DrawImage(im, 0, 0)

 DrawingArea1.Move(0, 0, im.W, im.H)

End

Modificare la dimensione del video agendo su uno Slider

In quest'altro esempio agendo su uno Slider, posto sul Form, si potrà modificare il video ripreso dalla webcam.

Private mp As MediaPlayer 


Public Sub Form_Open()

 With mp = New MediaPlayer
   .URL = "v4l2:///dev/video0"
   .SetWindow(PictureBox1)
   .play
 End With

 Slider1.Value = 50

 With PictureBox1
   .Image = mp.Video.Image.Stretch((mp.Video.Image.W * Slider1.Value) / 50, (mp.Video.Image.H * Slider1.Value) / 50)
   .Resize(PictureBox1.Image.W, PictureBox1.Image.H)
 End With

End


Public Sub Slider1_Change()

 With PictureBox1
   .Image = mp.Video.Image.Stretch((mp.Video.Image.W * Slider1.Value) / 50, (mp.Video.Image.H * Slider1.Value) / 50)
   .Resize(PictureBox1.Image.W, PictureBox1.Image.H)
 End With

 End

In quest'altro esempio, simile al precedente, useremo una DrawingArea:

Private DrawingArea1 As DrawingArea
Private mp As MediaPlayer
Private ms As New Short[2]


Public Sub Form_Open()

 Slider1.Value = 50

End


Public Sub ToggleButton1_Click()

 If ToggleButton1.Value Then 
   With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
     .Move(0, 0, 1, 1)
   End With
   With mp = New MediaPlayer
     If .State = Media.Playing Then
       .Stop
       .Close
       Return 
     Endif
     .URL = "v4l2:///dev/video0"
     .SetWindow(DrawingArea1)
     .Play()
   End With
   ms[0] = (mp.Video.Image.W * Slider1.Value) / 50
   ms[1] = (mp.Video.Image.H * Slider1.Value) / 50
 Else
   mp.Stop
   mp.Close
   mp = Null
   DrawingArea1.Clear
 Endif 

End


Public Sub Slider1_Change()

 If Not Object.IsValid(mp) Then Return 

 ms[0] = ((Screen.AvailableWidth / 2) * Slider1.Value) / 50   ' oppure: (mp.Video.Image.W * Slider1.Value) / 50
 ms[1] = ((Screen.AvailableHeight / 2) * Slider1.Value) / 50  ' oppure: (mp.Video.Image.H * Slider1.Value) / 50

 DrawingArea1.Refresh

End


Public Sub DrawingArea1_Draw()

 If Not Object.IsValid(mp) Then Return

 Dim im As Image = mp.Video.Image.Stretch(ms[0], ms[1])
 Paint.DrawImage(im, 0, 0)
 DrawingArea1.Move(0, 0, im.W, im.H)

End
 


Uso della Classe MediaPipeline

Questa modalità prevede l'utilizzo della Classe MediaPipeline che fornisce il supporto di collegamento dei vari plugin di GStreamer per consentire la ripresa video.

Esempio in un'applicazione grafica

Mostriamo di seguito un esempio essenziale con un'applicazione grafica. Il video sarà mostrato all'interno di una DrawingArea posta sul Form principale.

Private dr As DrawingArea
Private pl As MediaPipeline


Public Sub Form_Open()

    With dr = New DrawingArea(Me)
    .X = 10
    .Y = 10
    .W = 640
    .H = 480
  End With

End


Public Sub ToggleButton1_Click()

 If ToggleButton1.Value Then  
   Dim src, cnv, tim, bal, snk As MediaControl
   Dim ftr As MediaFilter
  
   pl = New MediaPipeline 
  
   src = New MediaControl(pl, "v4l2src")
   src["device"] = "/dev/video0"
' ...ma anche ad esempio così:
'    = "/dev/v4l/by-id/usb-Generic_Integrated_Camera_0001-video-index0"

   ftr = New MediaFilter(pl, "video/x-raw,width=640,height=480,framerate=30/1")
   cnv = New MediaControl(pl, "videoconvert")
' Nella finestra del video sarà mostrato anche il tempo trascorso dall'inizio della ripresa video:
   tim = New MediaControl(pl, "timeoverlay")
' Inseriamo il plugin "videobalance" di GStreamer...
   bal = New MediaControl(pl, "videobalance")
' ...e ne usiamo ad esempio la proprietà "brightness" impostando il suo valore a 0.8:
   bal["brightness"] = 0.5
   snk = New MediaControl(pl, "xvimagesink")
  
' Colleghiamo fra loro i cinque plugin di "GStreamer":
   src.LinkTo(ftr)
   ftr.LinkTo(cnv)
   cnv.LinkTo(tim)
   tim.LinkTo(bal)
   bal.LinkTo(snk)
   snk.SetWindow(dr)
  
' Avvia la ripresa video:
   pl.Play()

 Else 
  
' Arresta la ripresa video:
   pl.Stop
 Endif

End


Esempio in un'applicazione a riga di comando

Mostriamo di seguito un esempio essenziale con un'applicazione a riga di comando:

Public Sub Main()
 
  Dim pl As MediaPipeline
  Dim src, cnv, snk As MediaControl
  Dim ftr As MediaFilter
 
  pl = New MediaPipeline 
   
  src = New MediaControl(pl, "v4l2src")
  src["device"] = "/dev/video0"
' ...ma anche ad esempio così:
'    = "/dev/v4l/by-id/usb-Generic_Integrated_Camera_0001-video-index0"

  ftr = New MediaFilter(pl, "video/x-raw,width=640,height=480,framerate=30/1")
  cnv = New MediaControl(pl, "videoconvert")
  snk = New MediaControl(pl, "xvimagesink")
 
' Colleghiamo fra loro i due plugin di "GStreamer":
  src.LinkTo(ftr)
  ftr.LinkTo(cnv)
  cnv.LinkTo(snk)
  
' Avvia la ripresa video:
  pl.Play()
  
  While True
' Il tempo trascorso dall'inizio della ripresa video viene mostrato in console/Terminale:
    Write "\rTempo: " & Time(0, 0, 0, pl.Position * 1000)
    Wait 0.001
  Wend
     
End

Mostrare nel video anche il tempo trascorso

Per mostrare nella finestra del video anche il tempo trascorso dall'inizio della ripresa video, è necessario utilizzare (come abbiamo già visto nell'esempio con un'applicazione grafica) il plugin timeoverlay fornito da GStreamer:

Public Sub Main()
 
  Dim pl As MediaPipeline
  Dim src, cnv, tim, snk As MediaControl
  Dim ftr As MediaFilter
 
  pl = New MediaPipeline 
   
  src = New MediaControl(pl, "v4l2src")
  src["device"] = "/dev/video0"
' ...ma anche ad esempio così:
'    = "/dev/v4l/by-id/usb-Generic_Integrated_Camera_0001-video-index0"

  ftr = New MediaFilter(pl, "video/x-raw,width=640,height=480,framerate=30/1")
  cnv = New MediaControl(pl, "videoconvert")
  tim = New MediaControl(pl, "timeoverlay")
  snk = New MediaControl(pl, "xvimagesink")
  
' Colleghiamo fra loro i tre plugin di "GStreamer":
  src.LinkTo(ftr)
  ftr.LinkTo(cnv)
  cnv.LinkTo(tim)
  tim.LinkTo(snk)
  
' Avvia la ripresa video:
  pl.Play()
  
  Do
    Wait 0.01
  Loop
  
End


Effettuare le riprese video con due o più WebCam contemporaneamente

Per effettuare le riprese video con due o più WebCam contemporaneamente è necessario creare e gestire in modo separato una PipeLine per il flusso dati video di ciscuna WebCam.

Mostriamo un esempio pratico, nel quale si effettua la ripresa video di due WebCam. Il video di ciascuna WebCam sarà mostrato in due distinte DrawingArea poste sul Form:

Private dr1 As DrawingArea
Private dr2 As DrawingArea
Private pl1 As MediaPipeline
Private pl2 As MediaPipeline
Private bo As Boolean


Public Sub Form_Open()
 
 With dr1 = New DrawingArea(Me)
   .X = 10
   .Y = 10
   .W = 480
   .H = 320
 End With
 
 With dr2 = New DrawingArea(Me)
   .X = dr1.W + 40
   .Y = 10
   .W = 480
   .H = 320
 End With
 
 bo = True
  
End


Public Sub Public Sub ToggleButton1_Click()

 If ToggleButton1.Value Then
   Dim src1, src2, cnv1, cnv2, snk1, snk2 As MediaControl

   pl1 = New MediaPipeline 
   pl2 = New MediaPipeline 

   src1 = New MediaControl(pl1, "v4l2src")
   src1["device"] = "/dev/video0"
' ...ma anche ad esempio così:
'    = "/dev/v4l/by-id/usb-Generic_Integrated_Camera_0001-video-index0"

   src2 = New MediaControl(pl2, "v4l2src")
   src2["device"] = "/dev/video1"
' ...ma anche ad esempio così:
'    = "/dev/v4l/by-id/usb-Generic_Integrated_Camera_0001-video-index1"

   cnv1 = New MediaControl(pl1, "videoconvert")
   cnv2 = New MediaControl(pl2, "videoconvert")

   snk1 = New MediaControl(pl1, "xvimagesink")
   snk2 = New MediaControl(pl2, "xvimagesink")

' Colleghiamo fra loro i plugin di "GStreamer" della 1^ PipeLine:
   src1.LinkTo(cnv1)
   cnv1.LinkTo(snk1)

' Colleghiamo fra loro i plugin di "GStreamer" della 2^ PipeLine:
   src2.LinkTo(cnv2)
   cnv2.LinkTo(snk2)

' Impostiamo le due "DrawingArea" come superfici ove mostrare il video delle due WebCam:
   snk1.SetWindow(dr1)
   snk2.SetWindow(dr2)

' Avvia la ripresa video delle due webcam:
   pl1.Play()
   pl2.Play()

   While bo
     Wait 0.001
   Wend

' Chiude il flusso di dati video dalle webcam e libera la memoria:
   pl1.Close
   pl2.Close
  
' Chiude il Form:
   Me.Close
  
 Else
   bo = False
 Endif

End

Va detto che in taluni casi la parte finale della routine " Public Sub Button1_Click()" può creare un errore nell'impostazione dello status del media. Pertanto essa va sostituita con il seguente frammento di codice:

  ......
  ......
' Avvia la ripresa video delle due webcam:
  While bo
    pl1.Play()
' Potrebbe anche rendersi necessario porre uno stop momentaneo alla ripresa video, al fine di evitare un errore di status del media. (Verificare questa eventuale necessità).
    ' pl1.Stop
    
    pl2.Play()
' Potrebbe anche rendersi necessario porre uno stop momentaneo alla ripresa video, al fine di evitare un errore di status del media. (Verificare questa eventuale necessità).
    ' pl2.Stop
    Wait 0.001
  Wend
  
' Chiude il flusso di dati video dalle webcam e libera la memoria:
  pl1.Close
  pl2.Close
  
' Chiude il Form:
  Me.Close
  
End

Al riguardo va rilevato che questa soluzione rallenta la fluidità della ripresa video.


Ruotare il video mostrato

Per ruotare il video di una ripresa, è possibile utilizzare il plugin "videoflip" di GStreamer. [Nota 2]

Nel seguente esempio pratico si userà una "Enumerazione" (come riportato nelle risorse del plugin "videoflip" di GStreamer, ma bisognerà cambiare il trattino - presente nel nome di alcuni identificatori - in un trattino in basso.

Private Enum none = 0, clockwise, rotate_180, counterclockwise, horizontal_flip,
             vertical_flip, upper_left_diagonal, upper_right_diagonal, automatic
      

Public Sub Main()
 
 Dim pl As MediaPipeline
 Dim src, cnv, flp, snk As MediaControl
 Dim ftr As MediaFilter
 
 pl = New MediaPipeline 
  
 src = New MediaControl(pl, "v4l2src")
 src["device"] = "/dev/video0"
' ...ma anche ad esempio così:
'    = "/dev/v4l/by-id/usb-Generic_Integrated_Camera_0001-video-index0"

 ftr = New MediaFilter(pl, "video/x-raw,width=640,height=480,framerate=30/1")
 flp = New MediaControl(pl, "videoflip")
 flp["method"] = rotate_180
 cnv = New MediaControl(pl, "videoconvert")
 snk = New MediaControl(pl, "xvimagesink")
 
' Colleghiamo fra loro i plugin di "GStreamer":
 src.LinkTo(ftr)
 ftr.LinkTo(flp)
 flp.LinkTo(cnv)
 cnv.LinkTo(snk)
 
' Avvia la ripresa video:
 pl.Play()
 
 While True
' Il tempo trascorso dall'inizio della ripresa video viene mostrato in console/Terminale:
   Write "\rTempo: " & Time(0, 0, 0, pl.Position * 1000)
   Wait 0.001
 Wend
  
End


Note

[1] Riguardo all'Oggetto grafico da usare con il Metodo ".SetWindow()" della Classe "MediaPlayer", B. Minisini ha chiarito che esso necessita di un controllo che abbia una vera finestra X11 (o Wayland), altrimenti si userà il primo controllo genitore con una finestra reale, che di solito è quella di primo livello.

[2] Vedere la pagina di GStreamer relativa al plugin "videoflip": https://gstreamer.freedesktop.org/documentation/videofilter/videoflip.html?gi-language=c