#include "camera_memory.h" #ifdef LOG_TAG #undef LOG_TAG #endif #define LOG_TAG "aiqtool" extern uint32_t g_mmapNumber; int xioctl(int fh, int request, void* arg) { int ret; do { ret = ioctl(fh, request, arg); } while (-1 == ret && EINTR == errno); return ret; } void init_read(struct capture_info* cap_info, unsigned int buffer_size) { cap_info->buffers = (struct buffer*)calloc(1, sizeof(*cap_info->buffers)); if (!cap_info->buffers) { LOG_ERROR("Out of memory\\n"); exit(EXIT_FAILURE); } cap_info->buffers[0].length = buffer_size; cap_info->buffers[0].start = malloc(buffer_size); if (!cap_info->buffers[0].start) { LOG_ERROR("Out of memory\\n"); exit(EXIT_FAILURE); } } void init_mmap(struct capture_info* cap_info) { struct v4l2_requestbuffers req; CLEAR(req); req.count = g_mmapNumber; req.type = cap_info->capture_buf_type; req.memory = V4L2_MEMORY_MMAP; if (-1 == xioctl(cap_info->dev_fd, VIDIOC_REQBUFS, &req)) { if (EINVAL == errno) { LOG_ERROR("%s does not support " "memory mappingn", cap_info->dev_name); exit(EXIT_FAILURE); } else { errno_debug("VIDIOC_REQBUFS"); } } if (req.count < 2) { LOG_ERROR("Insufficient buffer memory on %s\\n", cap_info->dev_name); exit(EXIT_FAILURE); } cap_info->buffers = (struct buffer*)calloc(req.count, sizeof(*cap_info->buffers)); if (!cap_info->buffers) { LOG_ERROR("Out of memory\\n"); exit(EXIT_FAILURE); } for (cap_info->n_buffers = 0; cap_info->n_buffers < req.count; ++cap_info->n_buffers) { struct v4l2_buffer buf; struct v4l2_plane planes[FMT_NUM_PLANES]; CLEAR(buf); CLEAR(planes); buf.type = cap_info->capture_buf_type; buf.memory = V4L2_MEMORY_MMAP; buf.index = cap_info->n_buffers; if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == cap_info->capture_buf_type) { buf.m.planes = planes; buf.length = FMT_NUM_PLANES; } if (-1 == xioctl(cap_info->dev_fd, VIDIOC_QUERYBUF, &buf)) { errno_debug("VIDIOC_QUERYBUF"); } if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == cap_info->capture_buf_type) { cap_info->buffers[cap_info->n_buffers].length = buf.m.planes[0].length; cap_info->buffers[cap_info->n_buffers].start = mmap(NULL /* start anywhere */, buf.m.planes[0].length, PROT_READ | PROT_WRITE /* required */, MAP_SHARED /* recommended */, cap_info->dev_fd, buf.m.planes[0].m.mem_offset); } else { cap_info->buffers[cap_info->n_buffers].length = buf.length; cap_info->buffers[cap_info->n_buffers].start = mmap(NULL /* start anywhere */, buf.length, PROT_READ | PROT_WRITE /* required */, MAP_SHARED /* recommended */, cap_info->dev_fd, buf.m.offset); } if (MAP_FAILED == cap_info->buffers[cap_info->n_buffers].start) { errno_debug("mmap"); } memset(cap_info->buffers[cap_info->n_buffers].start, 0, cap_info->buffers[cap_info->n_buffers].length); } if (g_mmapNumber != 4) { LOG_INFO("mmap init finished.memory map: allocated/request: %u/%u \n", req.count, g_mmapNumber); } } void init_userp(struct capture_info* cap_info, unsigned int buffer_size) { struct v4l2_requestbuffers req; CLEAR(req); req.count = 4; req.type = cap_info->capture_buf_type; req.memory = V4L2_MEMORY_USERPTR; if (-1 == xioctl(cap_info->dev_fd, VIDIOC_REQBUFS, &req)) { if (EINVAL == errno) { LOG_ERROR("%s does not support " "user pointer i/on", cap_info->dev_name); exit(EXIT_FAILURE); } else { errno_debug("VIDIOC_REQBUFS"); } } cap_info->buffers = (struct buffer*)calloc(4, sizeof(*cap_info->buffers)); if (!cap_info->buffers) { LOG_ERROR("Out of memory\\n"); exit(EXIT_FAILURE); } for (cap_info->n_buffers = 0; cap_info->n_buffers < 4; ++cap_info->n_buffers) { cap_info->buffers[cap_info->n_buffers].length = buffer_size; cap_info->buffers[cap_info->n_buffers].start = malloc(buffer_size); if (!cap_info->buffers[cap_info->n_buffers].start) { LOG_ERROR("Out of memory\\n"); exit(EXIT_FAILURE); } } } int check_io_method(enum io_method io, unsigned int capabilities) { switch (io) { case IO_METHOD_READ: if (!(capabilities & V4L2_CAP_READWRITE)) { LOG_ERROR("Not support read i/o\n"); return -1; } break; case IO_METHOD_MMAP: case IO_METHOD_USERPTR: if (!(capabilities & V4L2_CAP_STREAMING)) { LOG_ERROR("Not support streaming i/o\n"); return -1; } break; } return 0; } int init_io_method(struct capture_info* cap_info, unsigned int size) { switch (cap_info->io) { case IO_METHOD_READ: init_read(cap_info, size); break; case IO_METHOD_MMAP: init_mmap(cap_info); break; case IO_METHOD_USERPTR: init_userp(cap_info, size); break; } return 0; }