Embedded System/Video4Linux2

[V4L2] Memory Mapping

임베지수 2017. 4. 2. 14:43

 

 

 

Input and output devices support this I/O method when the V4L2_CAP_STREAMING flag in the capabilities field of struct v4l2_capability returned by the VIDIOC_QUERYCAP ioctl is set. There are two streaming methods, to determine if the memory mapping flavor is supported applications must call the VIDIOC_REQBUFS ioctl.

 

A driver can support many sets of buffers. Each set is identified by a unique buffer type value. The sets are independent and each set can hold a different type of data. To access different sets at the same time different file descriptors must be used. One could use one file descriptor and set the buffer type field accordingly when calling VIDIOC_QBUF etc., but it makes the select() function ambiguous.

 

Before applications can access the buffers they must map them into their address space with the mmap() function. The location of the buffers in device memory which can be determined with the VIDIOC_QUERYBUF ioctl. The m.offset and length returned in a struct v4l2_buffer are passed as sixth and second parameter ro the mmap() function. The offset and length values must not be modified. Remember the buffers are allocated in physical memory, as opposed to virtual memory which can be swapped out to disk. Applications should free the buffers as soon as posible with the munmap() function.

 

Example

 

struct v4l2_requestbuffers reqbuf;
struct {
        void *start;
        size_t length;
} *buffers;
unsigned int i;

memset (&reqbuf, 0, sizeof (reqbuf));
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_MMAP;
reqbuf.count = 20;

if (-1 == ioctl (fd, VIDIOC_REQBUFS, &reqbuf)) {
        if (errno == EINVAL)
                printf ("Video capturing or mmap-streaming is not supported\n");
        else
                perror ("VIDIOC_REQBUFS");

        exit (EXIT_FAILURE);
}

/* We want at least five buffers. */

if (reqbuf.count < 5) {
        /* You may need to free the buffers here. */
        printf ("Not enough buffer memory\n");
        exit (EXIT_FAILURE);
}

buffers = calloc (reqbuf.count, sizeof (*buffers));

for (i = 0; i < reqbuf.count; i++) {
        struct v4l2_buffer buffer;

        memset (&buffer, 0, sizeof (buffer));
        buffer.type = reqbuf.type;
	buffer.memory = V4L2_MEMORY_MMAP;
        buffer.index = i;

        if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buffer)) {
                perror ("VIDIOC_QUERYBUF");
                exit (EXIT_FAILURE);
        }

        buffers[i].length = buffer.length; /* remember for munmap() */

        buffers[i].start = mmap (NULL, buffer.length,
                                 PROT_READ | PROT_WRITE, /* recommended */
                                 MAP_SHARED,             /* recommended */
                                 fd, buffer.m.offset);

        if (MAP_FAILED == buffers[i].start) {
                /* If you do not exit here you should unmap() and free()
                   the buffers mapped so far. */
                perror ("mmap");
                exit (EXIT_FAILURE);
        }
}

/* Cleanup. */

for (i = 0; i < reqbuf.count; i++)
        munmap (buffers[i].start, buffers[i].length);

 

'Embedded System > Video4Linux2' 카테고리의 다른 글

[V4L2] 이진화, 선 긋기  (5) 2017.04.02
[V4L2] Data Formats  (3) 2017.04.02
[V4L2] Querying Capabilities  (0) 2017.04.02
[V4L2] Opening and Closing Devices  (0) 2017.04.02
V4L2 API를 이용하여 영상획득 성공!!  (0) 2017.04.02