Red de conocimiento informático - Problemas con los teléfonos móviles - Programación V4L2

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)

{

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)

{

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)

{

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>

//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);