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

Da Gambas-it.org - Wikipedia.
(Creata pagina con 'La risorsa '''libv4l''' è una raccolta di librerie per la gestione dei dispositivi ''video4linux2'' evitando che si debba scrivere del codice separato, nella stessa classe, p...')
 
 
(16 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>
 
  Private Extern select_C(nfds As Integer, readfds As Pointer, writefds As Pointer, exceptfds As Pointer, timeout As Timeval) As Integer Exec "select"
 
  Private Extern select_C(nfds As Integer, readfds As Pointer, writefds As Pointer, exceptfds As Pointer, timeout As Timeval) As Integer Exec "select"
 
    
 
    
<FONT Color=gray>' ''FILE *fopen(const char *filename, const char *mode)''
 
' ''Opens the filename pointed to, by filename using the given mode.''</font>
 
Private Extern fopen(filename As String, mode As String) As Pointer
 
 
   
 
   
  <FONT Color=gray>' ''int fprintf(FILE *stream, const char *format, ...)''
+
  '''Public''' Sub Main()
' ''Sends formatted output to a stream.''</font>
+
 
Private Extern fprintf(fstream As Pointer, $format As String) As Integer
+
   Dim dispositivo, file_ppm As String
 
<FONT Color=gray>' ''size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
 
' ''Writes data from the array pointed to by ptr to the given stream.''</font>
 
Private Extern fwrite(ptr As Pointer, size As Integer, nmemb As Integer, fstream As Pointer) As Integer
 
 
<FONT Color=gray>' ''int fclose(FILE *stream)''
 
' ''Close the stream.''</font>
 
Private Extern fclose(fstream As Pointer) As Integer
 
 
 
Public Sub Main()
 
 
   Dim dispositivo 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
 
   Dim reqbuf As New V4l2_requestbuffers
 
   Dim reqbuf As New V4l2_requestbuffers
   Dim p, fex As Pointer
+
   Dim p As Pointer
 
   Dim st As Stream
 
   Dim st As Stream
 
   Dim buffers As New BUFFER[2]
 
   Dim buffers As New BUFFER[2]
 
   Dim tv As New Timeval
 
   Dim tv As New Timeval
 +
  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 pmm 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
+
  Repeat
    r = v4l2_ioctl_pointer(fd, VIDIOC_S_FMT, p)
+
    r = v4l2_ioctl_pointer(fd, VIDIOC_S_FMT, p)
  Loop Until r > -1
+
  Until r > -1
  If r = -1 Then Error.Raise("Errore !")
+
  If r = -1 Then Error.Raise("Errore !")
  Seek #st, 8
+
  Seek #st, 8
  Read #st, width
+
  Read #st, width
  Read #st, height
+
  Read #st, height
  Read #st, pix
+
  Read #st, pix
  If pix <> V4L2_PIX_FMT_RGB24 Then Error.Raise("Libv4l non accetta il formato RGB24.\nImpossibile procedere !")
+
  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
+
  If (width <> 640) Or (height <> 480) Then Print "Attenzione: il dispositivo imposterà l'immagine alle dimensioni";; width; "x"; height
  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)
  With reqbuf
+
  p = 0
    .count = 2
+
 
    .type = V4L2_BUF_TYPE_VIDEO_CAPTURE
+
  With reqbuf
    .memory_ = V4L2_MEMORY_MMAP
+
    .count = 2
  End With
+
    .type = V4L2_BUF_TYPE_VIDEO_CAPTURE
+
    .memory_ = V4L2_MEMORY_MMAP
       
+
  End With
  Do
+
 
    r = v4l2_ioctl_request(fd, VIDIOC_REQBUFS, reqbuf)
+
  Repeat
  Loop Until r > -1
+
    r = v4l2_ioctl_request(fd, VIDIOC_REQBUFS, reqbuf)
  If r = -1 Then Error.Raise("Errore !")
+
  Until r > -1
+
  If r = -1 Then Error.Raise("Errore !")
+
 
  p = Alloc(88)
+
  p = Alloc(SizeOf(gb.Byte), 88)
  st = Memory p For Read Write
+
  st = Memory p For Read Write
  For n_buff = 0 To reqbuf.count - 1
+
  For n_buff = 0 To reqbuf.count - 1
    Seek #st, 0
+
    Seek #st, 0
    Write #st, n_buff As Integer
+
    Write #st, n_buff As Integer
    Write #st, V4L2_BUF_TYPE_VIDEO_CAPTURE As Integer
+
    Write #st, V4L2_BUF_TYPE_VIDEO_CAPTURE As Integer
    Seek #st, 60
+
    Seek #st, 60
    Write #st, V4L2_MEMORY_MMAP As Integer
+
    Write #st, V4L2_MEMORY_MMAP As Integer
+
    Repeat
    Do
+
      r = v4l2_ioctl_pointer(fd, VIDIOC_QUERYBUF, p)
      r = v4l2_ioctl_pointer(fd, VIDIOC_QUERYBUF, p)
+
    Until r > -1
    Loop Until r > -1
+
    If r = -1 Then Error.Raise("Errore !")
    If r = -1 Then Error.Raise("Errore !")
+
    Seek #st, 72
         
+
    With buffers[n_buff] = New BUFFER
    Seek #st, 72
+
      Read #st, i
    With buffers[n_buff] = New BUFFER
+
      .length = i
      Read #st, i
+
    End With
      .length = i
+
    Seek #st, 64
    End With
+
    Read #st, offset
    Seek #st, 64
+
    buffers[n_buff].start = v4l2_mmap(Null, i, PROT_READ Or PROT_WRITE, MAP_SHARED, fd, offset)
    Read #st, offset
+
    If IsNull(buffers[n_buff].start) Then Error.Raise("Errore: puntatore nullo !")
    buffers[n_buff].start = v4l2_mmap(Null, i, PROT_READ Or PROT_WRITE, MAP_SHARED, fd, offset)
+
  Next
    If IsNull(buffers[n_buff].start) Then Error.Raise("Errore: puntatore nullo !")
+
  st.Close
  Next
+
  <FONT Color=gray>' ''Dealloca l'area di memoria precedentemente riservata e si assicura che il Puntatore non punti ad un indirizzo rilevante:''</font>
  st.Close
+
  Free(p)
  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>
 +
  File.Save(file_ppm, "P6\x0A" & CStr(width) & Chr(32) & CStr(height) & " 255\x0A")
 
    
 
    
  p = Alloc(88)
+
  fex = open file_ppm For Write
  st = Memory p For Write
+
  If IsNull(fex) Then Error.Raise("Impossibile aprire in scrittura il file immagine !")
  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
 
    Do
 
      r = v4l2_ioctl_pointer(fd, VIDIOC_QBUF, p)
 
    Loop Until r > -1
 
    If r = -1 Then Error.Raise("Errore !")
 
  Next
 
  st.Close
 
  Free(p)
 
 
  i = V4L2_BUF_TYPE_VIDEO_CAPTURE
 
  Do
 
    r = v4l2_ioctl_pointer(fd, VIDIOC_STREAMON, VarPtr(i))
 
  Loop Until r > -1
 
  If r = -1 Then Error.Raise("Errore !")
 
 
   
 
   
       
+
  Seek #st, 0
  Do
+
  Read #st, index
    tv.tv_sec = 1
+
  st.Close
    r = select_C(fd + 1, Null, Null, Null, tv)
+
<FONT Color=gray>' ''Dealloca l'area di memoria precedentemente riservata e si assicura che il Puntatore non punti ad un indirizzo rilevante:''</font>
  Loop Until r > -1
+
  Free(p)
  If r = -1 Then Error.Raise("Errore !")
+
  p = 0
+
 
  p = Alloc(88)
+
  p = buffers[index].start
  st = Memory p For Read Write
+
  If p == 0 Then Error.Raise("Errore !")
  Seek #st, 4
+
  Seek #fex, 15
  Write #st, V4L2_BUF_TYPE_VIDEO_CAPTURE As Integer
+
  For i = 1 To byte_usati
  Seek #st, 60
+
    Write #fex, Byte@(p) As Byte
  Write #st, V4L2_MEMORY_MMAP As Integer
+
    p = p + 1
  Do
+
  Next
    r = v4l2_ioctl_pointer(fd, VIDIOC_DQBUF, p)
+
  fex.Close
  Loop Until r > -1
 
  If r = -1 Then Error.Raise("Errore !")
 
  Seek #st, 8
 
  Read #st, byte_usati
 
     
 
  File.Save(file_ppm, Null)
 
  fex = fopen(file_ppm, "w")
 
  If IsNull(fex) Then Error.Raise("Impossibile aprire in scrittura il file immagine !")
 
 
  fprintf(fex, "P6\x0A" & CStr(width) & Chr(32) & CStr(height) & " 255\x0A")
 
  Seek #st, 0
 
  Read #st, index
 
  fwrite(buffers[index].start, byte_usati, 1, fex)
 
  fclose(fex)
 
  st.Close
 
  Free(p)
 
 
          
 
          
 
   
 
   
 
  <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 249: 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