Differenze tra le versioni di "Catturare un'immagine con una webcam mediante le funzioni esterne del API di libv4l2"

Da Gambas-it.org - Wikipedia.
 
(9 versioni intermedie di uno stesso utente non sono mostrate)
Riga 3: Riga 3:
 
La libreria ''libv4l2'', che qui ci interessa, mette a disposizione l'API ''v4l2'' per i dispositivi ''v4l2''.
 
La libreria ''libv4l2'', che qui ci interessa, mette a disposizione l'API ''v4l2'' per i dispositivi ''v4l2''.
  
Per poter fruire delle risorse fornite dalla libreria ''v4l2'' è necessario richiamare nell'applicazione Gambas la seguente libreria dinamica condivisa: "''libv4l2.so.0.0.0''"
+
Per poter fruire delle risorse fornite dalla libreria ''v4l2'' è necessario richiamare nell'applicazione Gambas la libreria condivisa: "''libv4l2.so.0.0.0'' ".
  
  
Mostriamo di seguito un possibile codice per la cattura di un'immagine attraverso una webcam. L'immagine sarà salvata in un file formato ''ppm'':
+
Mostriamo di seguito un possibile codice per la cattura di un'immagine attraverso una webcam.
Private Enum O_RDONLY = 0, O_WRONLY, O_RDWR, O_NONBLOCK = &2000
+
 
Private Enum PROT_NONE = 0, PROT_READ, PROT_WRITE
+
L'esempio funziona solo su sistemi a 64bit.
Private Const MAP_SHARED As Integer = 1
+
 
+
L'immagine sarà salvata in un file formato ''ppm'':
 
  Public Struct BUFFER
 
  Public Struct BUFFER
 
   start As Pointer
 
   start As Pointer
Riga 16: Riga 16:
 
  End Struct
 
  End Struct
 
   
 
   
Public Struct timeval
+
  Library "<FONT Color=blue>libv4l2:0.0.0</font>"
  tv_sec As Long
 
  tv_usec As Long
 
End Struct
 
 
 
  Library "libv4l2:0.0.0"
 
 
   
 
   
 
  Public Struct v4l2_requestbuffers
 
  Public Struct v4l2_requestbuffers
Riga 32: Riga 26:
 
   
 
   
 
  Private Enum V4L2_BUF_TYPE_VIDEO_CAPTURE = 1, V4L2_BUF_TYPE_VIDEO_OUTPUT, V4L2_BUF_TYPE_VIDEO_OVERLAY,
 
  Private Enum V4L2_BUF_TYPE_VIDEO_CAPTURE = 1, V4L2_BUF_TYPE_VIDEO_OUTPUT, V4L2_BUF_TYPE_VIDEO_OVERLAY,
               V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_BUF_TYPE_VBI_OUTPUT, V4L2_BUF_TYPE_SLICED_VBI_CAPTURE, V4L2_BUF_TYPE_SLICED_VBI_OUTPUT
+
               V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_BUF_TYPE_VBI_OUTPUT, V4L2_BUF_TYPE_SLICED_VBI_CAPTURE,
           
+
              V4L2_BUF_TYPE_SLICED_VBI_OUTPUT
 
  Private Enum V4L2_MEMORY_MMAP = 1, V4L2_MEMORY_USERPTR, V4L2_MEMORY_OVERLAY, V4L2_MEMORY_DMABUF
 
  Private Enum V4L2_MEMORY_MMAP = 1, V4L2_MEMORY_USERPTR, V4L2_MEMORY_OVERLAY, V4L2_MEMORY_DMABUF
           
 
 
  Private Const V4L2_PIX_FMT_RGB24 As Integer = 859981650
 
  Private Const V4L2_PIX_FMT_RGB24 As Integer = 859981650
 
  Private Const V4L2_FIELD_INTERLACED As Integer = 4
 
  Private Const V4L2_FIELD_INTERLACED As Integer = 4
Riga 70: Riga 63:
 
   
 
   
 
   
 
   
  Library "libc:6"
+
  Library "<FONT Color=red>libc:6</font>"
 +
 +
Public Struct timeval
 +
  tv_sec As Long
 +
  tv_usec As Long
 +
End Struct
 
   
 
   
 +
Private Enum O_RDONLY = 0, O_WRONLY, O_RDWR, O_NONBLOCK = &2000
 +
Private Enum PROT_NONE = 0, PROT_READ, PROT_WRITE
 +
Private Const MAP_SHARED As Integer = 1
 +
 
 
  <FONT Color=gray>' ''int select (int __nfds, fd_set *__restrict __readfds, fd_set *__restrict __writefds, fd_set *__restrict __exceptfds, struct timeval *__restrict __timeout)''
 
  <FONT Color=gray>' ''int select (int __nfds, fd_set *__restrict __readfds, fd_set *__restrict __writefds, fd_set *__restrict __exceptfds, struct timeval *__restrict __timeout)''
 
  ' ''Blocks the calling process until there is activity on any of the specified sets of file descriptors, or until the timeout period has expired.''</font>
 
  ' ''Blocks the calling process until there is activity on any of the specified sets of file descriptors, or until the timeout period has expired.''</font>
Riga 77: Riga 79:
 
    
 
    
 
   
 
   
  Public Sub Main()
+
  '''Public''' Sub Main()
+
 
   Dim dispositivo As String
+
   Dim dispositivo, file_ppm As String
  Dim file_ppm As String
 
 
   Dim fd, r, n_buff, i, offset As Integer
 
   Dim fd, r, n_buff, i, offset As Integer
 
   Dim width, height, index, byte_usati, pix As Integer
 
   Dim width, height, index, byte_usati, pix As Integer
Riga 90: Riga 91:
 
   Dim fex As File
 
   Dim fex As File
 
    
 
    
  dispositivo = "/dev/video0"
+
<FONT Color=gray>' ''Impostare il dispositivo video adeguato:''</font>
  file_ppm = "/tmp/immago.ppm"  <FONT Color=gray>' ''Il percorso ove sarà salvato il file immagine ppm creato''</font>
+
  dispositivo = "/dev/video0"
 
+
  file_ppm = "/tmp/immago.ppm"  <FONT Color=gray>' ''Il percorso ove sarà salvato il file immagine ppm creato''</font>
  fd = v4l2_open(dispositivo, O_RDWR Or O_NONBLOCK, 0)
+
 
  If fd < 0 Then Error.Raise("Impossibile aprire il file-device !")
+
  Write "\e[31mAttendere......\e[0m"
 +
  Flush
 +
 +
  fd = v4l2_open(dispositivo, O_RDWR Or O_NONBLOCK, 0)
 +
  If fd < 0 Then Error.Raise("Impossibile aprire il file-device !")
 
        
 
        
  p = Alloc(208)
+
  p = Alloc(SizeOf(gb.Byte), 208)
  st = Memory p For Read Write
+
  st = Memory p For Read Write
  Write #st, V4L2_BUF_TYPE_VIDEO_CAPTURE As Integer
+
  Write #st, V4L2_BUF_TYPE_VIDEO_CAPTURE As Integer
  Seek #st, 8
+
  Seek #st, 8
  Write #st, 640 As Integer
+
  Write #st, 640 As Integer
  Write #st, 480 As Integer
+
  Write #st, 480 As Integer
  Write #st, V4L2_PIX_FMT_RGB24 As Integer
+
  Write #st, V4L2_PIX_FMT_RGB24 As Integer
  Write #st, V4L2_FIELD_INTERLACED As Integer
+
  Write #st, V4L2_FIELD_INTERLACED As Integer
 
  Do
 
    r = v4l2_ioctl_pointer(fd, VIDIOC_S_FMT, p)
 
  Loop Until r > -1
 
  If r = -1 Then Error.Raise("Errore !")
 
  Seek #st, 8
 
  Read #st, width
 
  Read #st, height
 
  Read #st, pix
 
  If pix <> V4L2_PIX_FMT_RGB24 Then Error.Raise("Libv4l non accetta il formato RGB24.\nImpossibile procedere !")
 
  If (width <> 640) Or (height <> 480) Then Print "Attenzione: il dispositivo imposterà l'immagine alle dimensioni";; width; "x"; height
 
  st.Close
 
  Free(p)
 
 
  With reqbuf
 
    .count = 2
 
    .type = V4L2_BUF_TYPE_VIDEO_CAPTURE
 
    .memory_ = V4L2_MEMORY_MMAP
 
  End With
 
 
       
 
  Do
 
    r = v4l2_ioctl_request(fd, VIDIOC_REQBUFS, reqbuf)
 
  Loop Until r > -1
 
  If r = -1 Then Error.Raise("Errore !")
 
 
 
  p = Alloc(88)
 
  st = Memory p For Read Write
 
  For n_buff = 0 To reqbuf.count - 1
 
    Seek #st, 0
 
    Write #st, n_buff As Integer
 
    Write #st, V4L2_BUF_TYPE_VIDEO_CAPTURE As Integer
 
    Seek #st, 60
 
    Write #st, V4L2_MEMORY_MMAP As Integer
 
 
    Do
 
      r = v4l2_ioctl_pointer(fd, VIDIOC_QUERYBUF, p)
 
    Loop Until r > -1
 
    If r = -1 Then Error.Raise("Errore !")
 
         
 
    Seek #st, 72
 
    With buffers[n_buff] = New BUFFER
 
      Read #st, i
 
      .length = i
 
    End With
 
    Seek #st, 64
 
    Read #st, offset
 
    buffers[n_buff].start = v4l2_mmap(Null, i, PROT_READ Or PROT_WRITE, MAP_SHARED, fd, offset)
 
    If IsNull(buffers[n_buff].start) Then Error.Raise("Errore: puntatore nullo !")
 
  Next
 
  st.Close
 
  Free(p)
 
 
   
 
   
 
+
  Repeat
  p = Alloc(88)
+
    r = v4l2_ioctl_pointer(fd, VIDIOC_S_FMT, p)
  st = Memory p For Write
+
  Until r > -1
  For i = 0 To n_buff - 1
+
  If r = -1 Then Error.Raise("Errore !")
    Seek #st, 0
+
  Seek #st, 8
    Write #st, i As Integer
+
  Read #st, width
    Write #st, V4L2_BUF_TYPE_VIDEO_CAPTURE As Integer
+
  Read #st, height
    Seek #st, 60
+
  Read #st, pix
    Write #st, V4L2_MEMORY_MMAP As Integer
+
  If pix <> V4L2_PIX_FMT_RGB24 Then Error.Raise("Libv4l non accetta il formato RGB24.\nImpossibile procedere !")
    Do
+
  If (width <> 640) Or (height <> 480) Then Print "Attenzione: il dispositivo imposterà l'immagine alle dimensioni";; width; "x"; height
      r = v4l2_ioctl_pointer(fd, VIDIOC_QBUF, p)
+
  st.Close
    Loop Until r > -1
+
<FONT Color=gray>' ''Dealloca l'area di memoria precedentemente riservata e si assicura che il Puntatore non punti ad un indirizzo rilevante:''</font>
    If r = -1 Then Error.Raise("Errore !")
+
  Free(p)
  Next
+
  p = 0
  st.Close
+
 
  Free(p)
+
  With reqbuf
+
    .count = 2
  i = V4L2_BUF_TYPE_VIDEO_CAPTURE
+
    .type = V4L2_BUF_TYPE_VIDEO_CAPTURE
  Do
+
    .memory_ = V4L2_MEMORY_MMAP
    r = v4l2_ioctl_pointer(fd, VIDIOC_STREAMON, VarPtr(i))
+
  End With
  Loop Until r > -1
+
 
  If r = -1 Then Error.Raise("Errore !")
+
  Repeat
+
    r = v4l2_ioctl_request(fd, VIDIOC_REQBUFS, reqbuf)
       
+
  Until r > -1
  Do
+
  If r = -1 Then Error.Raise("Errore !")
    tv.tv_sec = 1
+
 
    r = select_C(fd + 1, Null, Null, Null, tv)
+
  p = Alloc(SizeOf(gb.Byte), 88)
  Loop Until r > -1
+
  st = Memory p For Read Write
  If r = -1 Then Error.Raise("Errore !")
+
  For n_buff = 0 To reqbuf.count - 1
+
    Seek #st, 0
  p = Alloc(88)
+
    Write #st, n_buff As Integer
  st = Memory p For Read Write
+
    Write #st, V4L2_BUF_TYPE_VIDEO_CAPTURE As Integer
  Seek #st, 4
+
    Seek #st, 60
  Write #st, V4L2_BUF_TYPE_VIDEO_CAPTURE As Integer
+
    Write #st, V4L2_MEMORY_MMAP As Integer
  Seek #st, 60
+
    Repeat
  Write #st, V4L2_MEMORY_MMAP As Integer
+
      r = v4l2_ioctl_pointer(fd, VIDIOC_QUERYBUF, p)
  Do
+
    Until r > -1
    r = v4l2_ioctl_pointer(fd, VIDIOC_DQBUF, p)
+
    If r = -1 Then Error.Raise("Errore !")
  Loop Until r > -1
+
    Seek #st, 72
  If r = -1 Then Error.Raise("Errore !")
+
    With buffers[n_buff] = New BUFFER
  Seek #st, 8
+
      Read #st, i
  Read #st, byte_usati
+
      .length = i
 +
    End With
 +
    Seek #st, 64
 +
    Read #st, offset
 +
    buffers[n_buff].start = v4l2_mmap(Null, i, PROT_READ Or PROT_WRITE, MAP_SHARED, fd, offset)
 +
    If IsNull(buffers[n_buff].start) Then Error.Raise("Errore: puntatore nullo !")
 +
  Next
 +
  st.Close
 +
  <FONT Color=gray>' ''Dealloca l'area di memoria precedentemente riservata e si assicura che il Puntatore non punti ad un indirizzo rilevante:''</font>
 +
  Free(p)
 +
  p = 0
 +
 
 +
  p = Alloc(SizeOf(gb.Byte), 88)
 +
  st = Memory p For Write
 +
  For i = 0 To n_buff - 1
 +
    Seek #st, 0
 +
    Write #st, i As Integer
 +
    Write #st, V4L2_BUF_TYPE_VIDEO_CAPTURE As Integer
 +
    Seek #st, 60
 +
    Write #st, V4L2_MEMORY_MMAP As Integer
 +
    Repeat
 +
      r = v4l2_ioctl_pointer(fd, VIDIOC_QBUF, p)
 +
    Until r > -1
 +
    If r = -1 Then Error.Raise("Errore !")
 +
  Next
 +
  st.Close
 +
<FONT Color=gray>' ''Dealloca l'area di memoria precedentemente riservata e si assicura che il Puntatore non punti ad un indirizzo rilevante:''</font>
 +
  Free(p)
 +
  p = 0
 +
 
 +
  i = V4L2_BUF_TYPE_VIDEO_CAPTURE
 +
  Repeat
 +
    r = v4l2_ioctl_pointer(fd, VIDIOC_STREAMON, VarPtr(i))
 +
  Until r > -1
 +
  If r = -1 Then Error.Raise("Errore !")
 +
     
 +
  Repeat
 +
    tv.tv_sec = 1
 +
    r = select_C(fd + 1, Null, Null, Null, tv)
 +
  Until r > -1
 +
  If r = -1 Then Error.Raise("Errore !")
 +
 
 +
  p = Alloc(SizeOf(gb.Byte), 88)
 +
  st = Memory p For Read Write
 +
  Seek #st, 4
 +
  Write #st, V4L2_BUF_TYPE_VIDEO_CAPTURE As Integer
 +
  Seek #st, 60
 +
  Write #st, V4L2_MEMORY_MMAP As Integer
 +
  Repeat
 +
    r = v4l2_ioctl_pointer(fd, VIDIOC_DQBUF, p)
 +
  Until r > -1
 +
  If r = -1 Then Error.Raise("Errore !")
 +
  Seek #st, 8
 +
  Read #st, byte_usati
 
    
 
    
 
   
 
   
 
  <FONT Color=gray>' ''Scrive il file immagine .ppm:''</font>
 
  <FONT Color=gray>' ''Scrive il file immagine .ppm:''</font>
  File.Save(file_ppm, "P6\x0A" & CStr(width) & Chr(32) & CStr(height) & " 255\x0A")
+
  File.Save(file_ppm, "P6\x0A" & CStr(width) & Chr(32) & CStr(height) & " 255\x0A")
 
    
 
    
  fex = open file_ppm For Write
+
  fex = open file_ppm For Write
  If IsNull(fex) Then Error.Raise("Impossibile aprire in scrittura il file immagine !")
+
  If IsNull(fex) Then Error.Raise("Impossibile aprire in scrittura il file immagine !")
 
   
 
   
  Seek #st, 0
+
  Seek #st, 0
  Read #st, index
+
  Read #st, index
  st.Close
+
  st.Close
  Free(p)
+
<FONT Color=gray>' ''Dealloca l'area di memoria precedentemente riservata e si assicura che il Puntatore non punti ad un indirizzo rilevante:''</font>
 
+
  Free(p)
  p = buffers[index].start
+
  p = 0
  Seek #fex, 15
+
 
  For i = 1 To byte_usati
+
  p = buffers[index].start
    Write #fex, Byte@(p) As Byte
+
  If p == 0 Then Error.Raise("Errore !")
    p = p + 1
+
  Seek #fex, 15
  Next
+
  For i = 1 To byte_usati
  fex.Close
+
    Write #fex, Byte@(p) As Byte
 +
    p = p + 1
 +
  Next
 +
  fex.Close
 
          
 
          
 
   
 
   
 
  <FONT Color=gray>' ''In chiusura:''</font>
 
  <FONT Color=gray>' ''In chiusura:''</font>
  i = V4L2_BUF_TYPE_VIDEO_CAPTURE
+
  i = V4L2_BUF_TYPE_VIDEO_CAPTURE
  Do
+
  Repeat
    r = v4l2_ioctl_pointer(fd, VIDIOC_STREAMON, VarPtr(i))
+
    r = v4l2_ioctl_pointer(fd, VIDIOC_STREAMON, VarPtr(i))
  Loop Until r > -1
+
  Until r > -1
  If r = -1 Then Error.Raise("Errore !")
+
  If r = -1 Then Error.Raise("Errore !")
 
   
 
   
  For i = 0 To n_buff - 1
+
  For i = 0 To n_buff - 1
    v4l2_munmap(buffers[i].start, buffers[i].length)
+
    v4l2_munmap(buffers[i].start, buffers[i].length)
  Next
+
  Next
 +
  v4l2_close(fd)
 
   
 
   
  v4l2_close(fd)
+
  Write "\rImmagine acquisita !"
 
    
 
    
 
  '''End'''
 
  '''End'''
 
  
  
Riga 242: Riga 250:
 
=Riferimenti=
 
=Riferimenti=
 
* http://linuxtv.org/downloads/v4l-dvb-apis/index.html
 
* http://linuxtv.org/downloads/v4l-dvb-apis/index.html
 +
* http://www.exploits.org/v4l/

Versione attuale delle 11:44, 12 apr 2023

La risorsa libv4l è una raccolta di librerie per la gestione dei dispositivi video4linux2 evitando che si debba scrivere del codice separato, nella stessa classe, per i diversi dispositivi. libv4l è composta da tre librerie differenti: libv4lconvert, libv4l1 e libv4l2.

La libreria libv4l2, che qui ci interessa, mette a disposizione l'API v4l2 per i dispositivi v4l2.

Per poter fruire delle risorse fornite dalla libreria v4l2 è necessario richiamare nell'applicazione Gambas la libreria condivisa: "libv4l2.so.0.0.0 ".


Mostriamo di seguito un possibile codice per la cattura di un'immagine attraverso una webcam.

L'esempio funziona solo su sistemi a 64bit.

L'immagine sarà salvata in un file formato ppm:

Public Struct BUFFER
  start As Pointer
  length As Integer
End Struct

Library "libv4l2:0.0.0"

Public Struct v4l2_requestbuffers
  count As Integer
  type As Integer
  memory_ As Integer
  reserved[2] As Integer
End Struct

Private Enum V4L2_BUF_TYPE_VIDEO_CAPTURE = 1, V4L2_BUF_TYPE_VIDEO_OUTPUT, V4L2_BUF_TYPE_VIDEO_OVERLAY,
             V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_BUF_TYPE_VBI_OUTPUT, V4L2_BUF_TYPE_SLICED_VBI_CAPTURE,
             V4L2_BUF_TYPE_SLICED_VBI_OUTPUT
Private Enum V4L2_MEMORY_MMAP = 1, V4L2_MEMORY_USERPTR, V4L2_MEMORY_OVERLAY, V4L2_MEMORY_DMABUF
Private Const V4L2_PIX_FMT_RGB24 As Integer = 859981650
Private Const V4L2_FIELD_INTERLACED As Integer = 4
Private Const VIDIOC_S_FMT As Long = 3234878981
Private Const VIDIOC_REQBUFS As Long = 3222558216
Private Const VIDIOC_QUERYBUF As Long = 3227014665
Private Const VIDIOC_QBUF As Long = 3227014671
Private Const VIDIOC_STREAMON As Long = 1074026002
Private Const VIDIOC_DQBUF As Long = 3227014673

' int v4l2_open(const char *file, int oflag, ...)
' Open a V4L2 device.
Private Extern v4l2_open(fl As String, oflag As Integer, alterum As Integer) As Integer

' int v4l2_ioctl(int fd, unsigned long int request, ...)
' Program a V4L2 device.
Private Extern v4l2_ioctl_pointer(fd As Integer, request As Long, arg As Pointer) As Integer Exec "v4l2_ioctl"

' int v4l2_ioctl(int fd, unsigned long int request, ...)
' Program a V4L2 device.
Private Extern v4l2_ioctl_request(fd As Integer, request As Long, arg As V4l2_requestbuffers) As Integer Exec "v4l2_ioctl"

' void *v4l2_mmap(void *start, size_t length, int prot, int flags, int fd, int64_t offset)
' Map device memory into application address space.
Private Extern v4l2_mmap(startP As Pointer, lengthI As Integer, prot As Integer, flags As Integer, fdI As Integer, offsetL As Long) As Pointer

' int v4l2_munmap(void *start, size_t length)
' Unmap device memory.
Private Extern v4l2_munmap(startP As Pointer, lengthI As Integer) As Integer

' int v4l2_close(int fd)
' Close a V4L2 device.
Private Extern v4l2_close(fd As Integer)


Library "libc:6"

Public Struct timeval
  tv_sec As Long
  tv_usec As Long
End Struct

Private Enum O_RDONLY = 0, O_WRONLY, O_RDWR, O_NONBLOCK = &2000
Private Enum PROT_NONE = 0, PROT_READ, PROT_WRITE
Private Const MAP_SHARED As Integer = 1
 
' int select (int __nfds, fd_set *__restrict __readfds, fd_set *__restrict __writefds, fd_set *__restrict __exceptfds, struct timeval *__restrict __timeout)
' Blocks the calling process until there is activity on any of the specified sets of file descriptors, or until the timeout period has expired.
Private Extern select_C(nfds As Integer, readfds As Pointer, writefds As Pointer, exceptfds As Pointer, timeout As Timeval) As Integer Exec "select"
 

Public Sub Main()
 
 Dim dispositivo, file_ppm As String
 Dim fd, r, n_buff, i, offset As Integer
 Dim width, height, index, byte_usati, pix As Integer
 Dim reqbuf As New V4l2_requestbuffers
 Dim p As Pointer
 Dim st As Stream
 Dim buffers As New BUFFER[2]
 Dim tv As New Timeval
 Dim fex As File
 
' Impostare il dispositivo video adeguato:
 dispositivo = "/dev/video0"
 file_ppm = "/tmp/immago.ppm"   ' Il percorso ove sarà salvato il file immagine ppm creato
 
 Write "\e[31mAttendere......\e[0m"
 Flush

 fd = v4l2_open(dispositivo, O_RDWR Or O_NONBLOCK, 0)
 If fd < 0 Then Error.Raise("Impossibile aprire il file-device !")
     
 p = Alloc(SizeOf(gb.Byte), 208)
 st = Memory p For Read Write
 Write #st, V4L2_BUF_TYPE_VIDEO_CAPTURE As Integer
 Seek #st, 8
 Write #st, 640 As Integer
 Write #st, 480 As Integer
 Write #st, V4L2_PIX_FMT_RGB24 As Integer
 Write #st, V4L2_FIELD_INTERLACED As Integer

 Repeat
   r = v4l2_ioctl_pointer(fd, VIDIOC_S_FMT, p)
 Until r > -1
 If r = -1 Then Error.Raise("Errore !")
 Seek #st, 8
 Read #st, width
 Read #st, height
 Read #st, pix
 If pix <> V4L2_PIX_FMT_RGB24 Then Error.Raise("Libv4l non accetta il formato RGB24.\nImpossibile procedere !")
 If (width <> 640) Or (height <> 480) Then Print "Attenzione: il dispositivo imposterà l'immagine alle dimensioni";; width; "x"; height
 st.Close
' Dealloca l'area di memoria precedentemente riservata e si assicura che il Puntatore non punti ad un indirizzo rilevante:
 Free(p)
 p = 0
 
 With reqbuf
   .count = 2
   .type = V4L2_BUF_TYPE_VIDEO_CAPTURE
   .memory_ = V4L2_MEMORY_MMAP
 End With
 
 Repeat
   r = v4l2_ioctl_request(fd, VIDIOC_REQBUFS, reqbuf)
 Until r > -1
 If r = -1 Then Error.Raise("Errore !")
 
 p = Alloc(SizeOf(gb.Byte), 88)
 st = Memory p For Read Write
 For n_buff = 0 To reqbuf.count - 1
   Seek #st, 0
   Write #st, n_buff As Integer
   Write #st, V4L2_BUF_TYPE_VIDEO_CAPTURE As Integer
   Seek #st, 60
   Write #st, V4L2_MEMORY_MMAP As Integer
   Repeat
     r = v4l2_ioctl_pointer(fd, VIDIOC_QUERYBUF, p)
   Until r > -1
   If r = -1 Then Error.Raise("Errore !")
   Seek #st, 72
   With buffers[n_buff] = New BUFFER
     Read #st, i
     .length = i
   End With
   Seek #st, 64
   Read #st, offset
   buffers[n_buff].start = v4l2_mmap(Null, i, PROT_READ Or PROT_WRITE, MAP_SHARED, fd, offset)
   If IsNull(buffers[n_buff].start) Then Error.Raise("Errore: puntatore nullo !")
 Next
 st.Close
 ' Dealloca l'area di memoria precedentemente riservata e si assicura che il Puntatore non punti ad un indirizzo rilevante:
 Free(p)
 p = 0
 
 p = Alloc(SizeOf(gb.Byte), 88)
 st = Memory p For Write
 For i = 0 To n_buff - 1
   Seek #st, 0
   Write #st, i As Integer
   Write #st, V4L2_BUF_TYPE_VIDEO_CAPTURE As Integer
   Seek #st, 60
   Write #st, V4L2_MEMORY_MMAP As Integer
   Repeat
     r = v4l2_ioctl_pointer(fd, VIDIOC_QBUF, p)
   Until r > -1
   If r = -1 Then Error.Raise("Errore !")
 Next
 st.Close
' Dealloca l'area di memoria precedentemente riservata e si assicura che il Puntatore non punti ad un indirizzo rilevante:
 Free(p)
 p = 0
 
 i = V4L2_BUF_TYPE_VIDEO_CAPTURE
 Repeat
   r = v4l2_ioctl_pointer(fd, VIDIOC_STREAMON, VarPtr(i))
 Until r > -1
 If r = -1 Then Error.Raise("Errore !")
      
 Repeat
   tv.tv_sec = 1
   r = select_C(fd + 1, Null, Null, Null, tv)
 Until r > -1
 If r = -1 Then Error.Raise("Errore !")
 
 p = Alloc(SizeOf(gb.Byte), 88)
 st = Memory p For Read Write
 Seek #st, 4
 Write #st, V4L2_BUF_TYPE_VIDEO_CAPTURE As Integer
 Seek #st, 60
 Write #st, V4L2_MEMORY_MMAP As Integer
 Repeat
   r = v4l2_ioctl_pointer(fd, VIDIOC_DQBUF, p)
 Until r > -1
 If r = -1 Then Error.Raise("Errore !")
 Seek #st, 8
 Read #st, byte_usati
  

' Scrive il file immagine .ppm:
 File.Save(file_ppm, "P6\x0A" & CStr(width) & Chr(32) & CStr(height) & " 255\x0A")
  
 fex = open file_ppm For Write
 If IsNull(fex) Then Error.Raise("Impossibile aprire in scrittura il file immagine !")

 Seek #st, 0
 Read #st, index
 st.Close
' Dealloca l'area di memoria precedentemente riservata e si assicura che il Puntatore non punti ad un indirizzo rilevante:
 Free(p)
 p = 0
 
 p = buffers[index].start
 If p == 0 Then Error.Raise("Errore !")
 Seek #fex, 15
 For i = 1 To byte_usati
   Write #fex, Byte@(p) As Byte
   p = p + 1
 Next
 fex.Close
       

' In chiusura:
 i = V4L2_BUF_TYPE_VIDEO_CAPTURE
 Repeat
   r = v4l2_ioctl_pointer(fd, VIDIOC_STREAMON, VarPtr(i))
 Until r > -1
 If r = -1 Then Error.Raise("Errore !")

 For i = 0 To n_buff - 1
   v4l2_munmap(buffers[i].start, buffers[i].length)
 Next
 v4l2_close(fd)

 Write "\rImmagine acquisita !"
 
End


Riferimenti