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

Da Gambas-it.org - Wikipedia.
 
(8 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.
 
Mostriamo di seguito un possibile codice per la cattura di un'immagine attraverso una webcam.
  
Funziona solo su sistemi a 64bit.
+
L'esempio funziona solo su sistemi a 64bit.
  
 
L'immagine sarà salvata in un file formato ''ppm'':
 
L'immagine sarà salvata in un file formato ''ppm'':
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
 
 
 
  Public Struct BUFFER
 
  Public Struct BUFFER
 
   start As Pointer
 
   start As Pointer
Riga 20: 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 36: 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 74: 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 81: 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 94: 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 246: 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