Programación V4L2
v4L2 es un marco de programación para dispositivos USB sin controlador UVC. Se utiliza principalmente para capturar cámaras USB, etc. El modo de programación es el siguiente: Después de abrir el dispositivo de video, puede configurar las propiedades de. el dispositivo de vídeo, como recortar, escalar, etc. Este paso es opcional. En la programación de Linux, la función ioctl se usa generalmente para administrar el canal de E/S del dispositivo:
extern int ioctl (int __fd, unsigned long int __request, ...) __THROW;
__fd: ID del dispositivo, como la cámaraFd devuelta después de abrir el canal de vídeo con la función de apertura;
__request: El identificador de comando específico.
En el desarrollo V4L2, generalmente se utilizan los siguientes identificadores de comando:
VIDIOC_REQBUFS: asigna memoria
VIDIOC_QUERYBUF: almacena en caché los datos asignados en VIDIOC_REQBUFS Convertir a dirección física
VIDIOC_QUERYCAP: Función de consulta del controlador
VIDIOC_ENUM_FMT: Obtener el formato de vídeo soportado por el controlador actual
VIDIOC_S_FMT: Establecer el formato de captura de vídeo del controlador actual
p>
VIDIOC_G_FMT: Leer el formato de captura de frecuencia del controlador actual
VIDIOC_TRY_FMT: Verificar el formato de visualización del controlador actual
VIDIOC_CROPCAP: Consultar la poda del controlador capacidad
VIDIOC_S_CROP: establece el cuadro de la señal de video
VIDIOC_G_CROP: lee el cuadro de la señal de video
VIDIOC_QBUF: vuelve a colocar los datos en la cola de caché
VIDIOC_DQBUF: Coloca los datos de lectura desde el caché
VIDIOC_STREAMON: Inicia la función de visualización de video
VIDIOC_STREAMOFF: Finaliza la función de visualización de video
VIDIOC_QUERYSTD: Verifique los estándares admitidos por el dispositivo de video actual, como PAL o NTSC.
Algunas de estas llamadas IO son obligatorias y otras son opcionales. 1. Abra el archivo del dispositivo.
int fd=open(”/dev/video0″, O_RDWR);
2. Obtenga la capacidad del dispositivo y vea qué funciones tiene, por ejemplo, si tiene entrada de vídeo, o entrada y salida de audio, etc. VIDIOC_QUERYCAP, estructura v4l2_capability
v4l2_std_id std;
do {
ret= ioctl(fd, VIDIOC_QUERYSTD, amp; std);
} while (ret == -1 amp; errno == EAGAIN);
interruptor (estándar) {
caso V4L2_STD_NTSC:
//… …
caso V4L2_STD_PAL:
//…
}
3. Seleccione la entrada de video, un dispositivo de video puede tener múltiples entradas de video. VIDIOC_S_INPUT, struct v4l2_input (opcional)
4. Configure el formato de video y el formato de cuadro. El formato incluye PAL, NTSC y el formato de cuadro incluye ancho y alto.
VIDIOC_S_STD, VIDIOC_S_FMT, struct v4l2_std_id, struct v4l2_format
struct v4l2_format fmt;
/*
La estructura de v4l2_format es la siguiente :
struct v4l2_format
{
enum v4l2_buf_type type; // El tipo de flujo de datos siempre debe ser V4L2_BUF_TYPE_VIDEO_CAPTURE
union
{
struct v4l2_pix_format pix;
struct v4l2_window win;
struct v4l2_vbi_format vbi;
__u8 raw_data[200];
} fmt;
};
struct v4l2_pix_format
{
__u32 ancho; debe ser 16 múltiplos de
__u32 height; // la altura debe ser un múltiplo de 16
__u32 pixelformat; // tipo de almacenamiento de datos de vídeo, como YUV 4:2:2 o RGB
p>enum v4l2_field campo;
__u32 bytesperline;
__u32 tamañoimagen;
enum v4l2_colorspace espacio de colores;
__u32 priv;
};
*/
Ejemplo:
memset (amp; fmt, 0, sizeof(fmt ));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 320;
fmt.fmt.pix.height = 240;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
if (ioctl(fd, VIDIOC_S_FMT, amp; fmt) lt; 0)
{ p>
printf(falló el formato establecido\n);
//return 0;
}
5. buffer, generalmente no más de 5 .
struct v4l2_requestbuffers
struct v4l2_requestbuffers
{
__u32 count; // Cantidad de caché, es decir, cuántas fotos se guardan en la cola de caché
enum v4l2_buf_type type; // El tipo de flujo de datos siempre debe ser V4L2_BUF_TYPE_VIDEO_CAPTURE
enum v4l2_memory Memory // V4L2_MEMORY_MMAP o V4L2_MEMORY_USERPTR
__u32 reservado[2];
};
Ejemplo:
struct v4l2_requestbuffers req;
memset(amp;req, 0, sizeof (req));
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd,VIDIOC_REQBUFS, amp ; req) == -1)
{
error(VIDIOC_REQBUFS error \n);
//return -1;
}
6. Solicite memoria física
Asigne el búfer de fotogramas aplicado al espacio del usuario, para que pueda operar directamente los fotogramas recopilados sin copiarlos.
Coloque todos los buffers de fotogramas aplicados en la cola para almacenar los datos recopilados.VIDIOC_QBUF, struct v4l2_buffer
VideoBuffer* buffers = calloc( req.count, sizeof(VideoBuffer) );
printf (sizeof(VideoBuffer) es d\n,sizeof(VideoBuffer));
struct v4l2_buffer buf;
for (numBufs = 0; numBufs lt; req.count; numBufs )
{
memset( amp;buf, 0, sizeof(buf) );
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf. memoria = V4L2_MEMORY_MMAP;
buf.index = numBufs;
if (ioctl(fd, VIDIOC_QUERYBUF, amp;buf) lt; 0)
{ p>
printf(VIDIOC_QUERYBUF error\n);
//return -1;
}
printf(buf len es d\ n, sizeof(buf));
//Asignación de memoria
búferes[numBufs].length = buf.length;
búferes[numBufs].offset = ( size_t) buf.m.offset;
buffers[numBufs].start = mmap (NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
printf(buffers.length = d, buffers.offset = d, buffers.start[0] = d\n, buffers[numBufs].length, buffers[numBufs].offset, buffers[numBufs].start[ 0] );
printf(buf2 len es d\n, sizeof(buffers[numBufs].start));
if (buffers[numBufs].start == MAP_FAILED) p>
{
error(error de buffers\n);
//return -1;
}
if (ioctl (fd, VIDIOC_QBUF, amp;buf) lt; 0)
{
printf(VIDIOC_QBUF error\n);
//return -1 ;
}
}
7. Iniciar la colección de vídeos.
enum v4l2_buf_type tipo;
tipo = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl (fd, VIDIOC_STREAMON, amp; tipo) lt; 0)
{
printf(VIDIOC_STREAMON error\n);
// return -1;
}
8. Obtenga el búfer de fotogramas de los datos recopilados y obtenga los datos recopilados originales. VIDIOC_DQBUF, vuelva a ingresar el búfer al final de la cola para que pueda recopilarse cíclicamente. VIDIOC_QBUF
if (ioctl(fd, VIDIOC_DQBUF, amp;buf) lt; 0)
{
error(VIDIOC_DQBUF falló.\n); p>
p>
//return -1;
}
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
car unsigned *ptcur = buffers[numBufs].start;
DEBUG(buf.bytesused = d \n,buf.bytesused);
int i1 ;
for(i1=0; i1lt;buf.bytesused; i1)
{
if((buffers[numBufs].start[i1] = = 0x000000FF) amp; amp; (buffers[numBufs].start[i1 1] == 0x000000C4))
{
DEBUG(¡tabla huffman encontrada! \nbuf.bytesused = d \nFFC4 = d\n, buf.byteused, i1
romper
}
}
if(i1 = = buf.bytesused) printf(¡la tabla huffman no existe! \n
int i
for(i=0; ilt; buf.bytesused; i )
{
if((buffers[numBufs].start[i] == 0x000000FF) amp; amp; (buffers[numBufs].start[i 1] == 0x000000D8)) break;
ptcur;
}
DEBUG(i=d, FF=02x, D8=02x\n, i, buffers[numBufs].start [i], buffers [numBufs].start[i 1]);
int imagesize =buf.bytesused - i;
DEBUG(buf.bytesused = d \n,buf .bytesused);
DEBUG (tamaño de imagen = d \n, tamaño de imagen
9.
VIDIOC_STREAMOFF
10. Apague el dispositivo de vídeo. cerrar(fd);