#include "camera_capture.h" #ifdef LOG_TAG #undef LOG_TAG #endif #define LOG_TAG "aiqtool" void process_image(struct capture_info* cap_info, const void* p, int size) { static int image_index = 0; LOG_DEBUG("image_index %d\n", image_index++); if (cap_info->out_fp) { fwrite(p, size, 1, cap_info->out_fp); fflush(cap_info->out_fp); } } int read_frame(struct capture_info* cap_info) { struct v4l2_buffer buf; unsigned int i, bytesused; switch (cap_info->io) { case IO_METHOD_READ: if (-1 == read(cap_info->dev_fd, cap_info->buffers[0].start, cap_info->buffers[0].length)) { switch (errno) { case EAGAIN: return 0; case EIO: /* Could ignore EIO, see spec. */ /* fall through */ default: errno_debug("read"); } } process_image(cap_info, cap_info->buffers[0].start, cap_info->buffers[0].length); break; case IO_METHOD_MMAP: CLEAR(buf); buf.type = cap_info->capture_buf_type; buf.memory = V4L2_MEMORY_MMAP; if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == cap_info->capture_buf_type) { struct v4l2_plane planes[FMT_NUM_PLANES]; buf.m.planes = planes; buf.length = FMT_NUM_PLANES; } if (device_dqbuf(cap_info->dev_fd, &buf) == -1) break; assert(buf.index < cap_info->n_buffers); if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == cap_info->capture_buf_type) { bytesused = buf.m.planes[0].bytesused; } else { bytesused = buf.bytesused; } process_image(cap_info, cap_info->buffers[buf.index].start, bytesused); device_qbuf(cap_info->dev_fd, &buf); break; case IO_METHOD_USERPTR: CLEAR(buf); buf.type = cap_info->capture_buf_type; buf.memory = V4L2_MEMORY_USERPTR; if (device_dqbuf(cap_info->dev_fd, &buf) == -1) break; for (i = 0; i < cap_info->n_buffers; ++i) { if (buf.m.userptr == (unsigned long)cap_info->buffers[i].start && buf.length == cap_info->buffers[i].length) { break; } } assert(i < cap_info->n_buffers); process_image(cap_info, (void*)buf.m.userptr, buf.bytesused); device_qbuf(cap_info->dev_fd, &buf); break; } return 1; } int read_frame(int handler, int index, struct capture_info* cap_info, CaptureCallBack callback) { struct v4l2_buffer buf; unsigned int i, bytesused; switch (cap_info->io) { case IO_METHOD_READ: if (-1 == read(cap_info->dev_fd, cap_info->buffers[0].start, cap_info->buffers[0].length)) { switch (errno) { case EAGAIN: return 0; case EIO: /* Could ignore EIO, see spec. */ /* fall through */ default: errno_debug("read"); } } if (callback) callback(handler, index, cap_info->buffers[0].start, cap_info->buffers[0].length); break; case IO_METHOD_MMAP: CLEAR(buf); struct v4l2_plane planes[FMT_NUM_PLANES]; buf.type = cap_info->capture_buf_type; buf.memory = V4L2_MEMORY_MMAP; if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == cap_info->capture_buf_type) { buf.m.planes = planes; buf.length = FMT_NUM_PLANES; } if (device_dqbuf(cap_info->dev_fd, &buf) == -1) break; assert(buf.index < cap_info->n_buffers); if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == cap_info->capture_buf_type) { bytesused = buf.m.planes[0].bytesused; } else { bytesused = buf.bytesused; } if (callback) { callback(handler, index, cap_info->buffers[buf.index].start, bytesused); } memset(cap_info->buffers[buf.index].start, 0, bytesused); device_qbuf(cap_info->dev_fd, &buf); break; case IO_METHOD_USERPTR: CLEAR(buf); buf.type = cap_info->capture_buf_type; buf.memory = V4L2_MEMORY_USERPTR; if (device_dqbuf(cap_info->dev_fd, &buf) == -1) break; for (i = 0; i < cap_info->n_buffers; ++i) if (buf.m.userptr == (unsigned long)cap_info->buffers[i].start && buf.length == cap_info->buffers[i].length) { break; } assert(i < cap_info->n_buffers); if (callback) { callback(handler, index, (void*)buf.m.userptr, buf.bytesused); } device_qbuf(cap_info->dev_fd, &buf); break; } return 1; } void stop_capturing(struct capture_info* cap_info) { enum v4l2_buf_type type; switch (cap_info->io) { case IO_METHOD_READ: /* Nothing to do. */ break; case IO_METHOD_MMAP: case IO_METHOD_USERPTR: type = cap_info->capture_buf_type; device_streamoff(cap_info->dev_fd, &type); break; } } void start_capturing(struct capture_info* cap_info) { unsigned int i; enum v4l2_buf_type type; LOG_DEBUG("#### start_capturing, cap_info.dev_name:%s\n", cap_info->dev_name); switch (cap_info->io) { case IO_METHOD_READ: /* Nothing to do. */ break; case IO_METHOD_MMAP: LOG_DEBUG("IO_METHOD_MMAP, buffer number:%d\n", cap_info->n_buffers); for (i = 0; i < cap_info->n_buffers; ++i) { struct v4l2_buffer buf; CLEAR(buf); buf.type = cap_info->capture_buf_type; buf.memory = V4L2_MEMORY_MMAP; buf.index = i; if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == cap_info->capture_buf_type) { struct v4l2_plane planes[FMT_NUM_PLANES]; buf.m.planes = planes; buf.length = FMT_NUM_PLANES; } device_qbuf(cap_info->dev_fd, &buf); } type = cap_info->capture_buf_type; device_streamon(cap_info->dev_fd, &type); break; case IO_METHOD_USERPTR: for (i = 0; i < cap_info->n_buffers; ++i) { struct v4l2_buffer buf; CLEAR(buf); buf.type = cap_info->capture_buf_type; buf.memory = V4L2_MEMORY_USERPTR; buf.index = i; buf.m.userptr = (unsigned long)cap_info->buffers[i].start; buf.length = cap_info->buffers[i].length; if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == cap_info->capture_buf_type) { struct v4l2_plane planes[FMT_NUM_PLANES]; planes[0].m.userptr = (unsigned long)cap_info->buffers[i].start; planes[0].length = cap_info->buffers[i].length; buf.m.planes = planes; buf.length = FMT_NUM_PLANES; } device_qbuf(cap_info->dev_fd, &buf); } type = cap_info->capture_buf_type; device_streamon(cap_info->dev_fd, &type); break; } } void uninit_device(struct capture_info* cap_info) { unsigned int i; switch (cap_info->io) { case IO_METHOD_READ: free(cap_info->buffers[0].start); break; case IO_METHOD_MMAP: for (i = 0; i < cap_info->n_buffers; ++i) if (-1 == munmap(cap_info->buffers[i].start, cap_info->buffers[i].length)) { errno_debug("munmap"); } break; case IO_METHOD_USERPTR: for (i = 0; i < cap_info->n_buffers; ++i) { free(cap_info->buffers[i].start); } break; } free(cap_info->buffers); device_close(cap_info->dev_fd); cap_info->dev_fd = -1; } int init_device(struct capture_info* cap_info) { struct v4l2_capability cap; struct v4l2_cropcap cropcap; struct v4l2_crop crop; struct v4l2_format fmt; unsigned int min; int ret; cap_info->dev_fd = device_open(cap_info->dev_name); if (-1 != device_querycap(cap_info->dev_fd, &cap)) { if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) && !(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE)) { LOG_ERROR("%s is no video capture device\n", cap_info->dev_name); return -1; } } if (-1 == check_io_method(cap_info->io, cap.capabilities)) { return -1; } CLEAR(cropcap); cropcap.type = cap_info->capture_buf_type; crop.type = cap_info->capture_buf_type; // crop.c = cropcap.defrect; /* reset to default */ crop.c.left = 0; crop.c.top = 0; crop.c.width = cap_info->width; crop.c.height = cap_info->height; if (cap_info->link == link_to_isp) { device_cropcap(cap_info->dev_fd, &cropcap, &crop); } CLEAR(fmt); if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) { cap_info->capture_buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; } else if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE) { cap_info->capture_buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; } if (cap_info->format) { fmt.type = cap_info->capture_buf_type; fmt.fmt.pix.width = cap_info->width; fmt.fmt.pix.height = cap_info->height; fmt.fmt.pix.pixelformat = cap_info->format; fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; ret = device_setformat(cap_info->dev_fd, &fmt); if (ret) { LOG_ERROR("%s set format failed\n", cap_info->dev_name); } else { LOG_INFO("%s set format success\n", cap_info->dev_name); } } else { device_getformat(cap_info->dev_fd, &fmt); } /* Buggy driver paranoia. */ min = fmt.fmt.pix.width * 2; if (fmt.fmt.pix.bytesperline < min) { fmt.fmt.pix.bytesperline = min; } min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height; if (fmt.fmt.pix.sizeimage < min) { fmt.fmt.pix.sizeimage = min; } init_io_method(cap_info, fmt.fmt.pix.sizeimage); return 0; }