123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright (C) 2021 StarFive Technology Co., Ltd.
- */
- #include <sys/mman.h>
- #include <libv4l2.h>
- #include <sys/ioctl.h>
- #include "common.h"
- #include "stf_v4l2.h"
- #include "stf_log.h"
- #define FILENAME_MAX_LEN 30
- struct stfisp_fw_info {
- char filename[FILENAME_MAX_LEN];
- };
- struct v4l2_subdev_frame_size_enum {
- __u32 index;
- __u32 pad;
- __u32 code;
- __u32 min_width;
- __u32 max_width;
- __u32 min_height;
- __u32 max_height;
- __u32 which;
- __u32 reserved[8];
- };
- #define VIDIOC_STFISP_LOAD_FW \
- _IOW('V', BASE_VIDIOC_PRIVATE + 1, struct stfisp_fw_info)
- #define VIDIOC_SUBDEV_ENUM_FRAME_SIZE \
- _IOWR('V', 74, struct v4l2_subdev_frame_size_enum)
- #define MEDIA_BUS_FMT_SRGGB10_1X10 0x300f
- /**
- Do ioctl and retry if error was EINTR ("A signal was caught during the ioctl() operation."). Parameters are the same as on ioctl.
- \param fd file descriptor
- \param request request
- \param argp argument
- \returns result from ioctl
- */
- int xioctl(int fd, int request, void* argp)
- {
- int r;
- // TODO: the orign is v4l2_ioctl()
- do r = ioctl(fd, request, argp);
- while (-1 == r && EINTR == errno);
- return r;
- }
- void sensor_image_size_info(V4l2Param_t *param)
- {
- int fd = 0;
- uint32_t i = 0;
- struct v4l2_subdev_frame_size_enum frame_size;
- LOG(STF_LEVEL_DEBUG, "go in sensor_image_size_info....\n");
- fd = open(param->device_name, O_RDWR /* required */ | O_NONBLOCK, 0);
- if (-1 == fd) {
- LOG(STF_LEVEL_ERR, "Cannot open '%s': %d, %s\n", param->device_name, errno, strerror(errno));
- close(fd);
- exit(EXIT_FAILURE);
- }
- for (i = 0; i < 4; i++) {
- frame_size.index = i;
- frame_size.code = MEDIA_BUS_FMT_SRGGB10_1X10;
- if (-1 == ioctl(fd, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, &frame_size)) {
- close(fd);
- errno_exit("VIDIOC_SIZE_INFO");
- }
- LOG(STF_LEVEL_DEBUG, "image_size: width[%d] = %d, height[%d] = %d \n",
- i, frame_size.min_width, i, frame_size.min_height);
- }
- close(fd);
- }
- void loadfw_start(char *filename, V4l2Param_t *param)
- {
- struct stfisp_fw_info fw_info = {0};
- int fd = 0;
- LOG(STF_LEVEL_TRACE, "Enter\n");
- fd = open(param->device_name, O_RDWR /* required */ | O_NONBLOCK, 0);
- if (-1 == fd) {
- LOG(STF_LEVEL_ERR, "Cannot open '%s': %d, %s\n", param->device_name, errno, strerror(errno));
- exit(EXIT_FAILURE);
- }
- if (filename && (strlen(filename) < FILENAME_MAX_LEN)) {
- memcpy(fw_info.filename, filename, strlen(filename) + 1);
- }
- LOG(STF_LEVEL_INFO, "VIDIOC_STFISP_LOAD_FW = 0x%lx, filename = %s, size = %lu, device=%s\n",
- VIDIOC_STFISP_LOAD_FW, fw_info.filename, sizeof(struct stfisp_fw_info), param->device_name);
- if (-1 == ioctl(fd, VIDIOC_STFISP_LOAD_FW, &fw_info)) {
- if (EINVAL == errno) {
- close(fd);
- LOG(STF_LEVEL_ERR, "%s is no V4L2 device\n", param->device_name);
- exit(EXIT_FAILURE);
- } else {
- close(fd);
- errno_exit("VIDIOC_STFISP_LOAD_FW");
- }
- }
- close(fd);
- LOG(STF_LEVEL_TRACE, "Exit\n");
- }
- static void convert_v4l2_mem_type(int iomthd, enum v4l2_memory *mem_type)
- {
- if (iomthd < IO_METHOD_MMAP || iomthd > IO_METHOD_READ) {
- LOG(STF_LEVEL_ERR, "iomthd %d out of range\n", iomthd);
- exit(EXIT_FAILURE);
- }
- switch (iomthd) {
- case IO_METHOD_MMAP:
- *mem_type = V4L2_MEMORY_MMAP;
- break;
- case IO_METHOD_USERPTR:
- *mem_type = V4L2_MEMORY_USERPTR;
- break;
- case IO_METHOD_DMABUF:
- *mem_type = V4L2_MEMORY_DMABUF;
- break;
- case IO_METHOD_READ:
- *mem_type = 0; // not use memory machanism
- break;
- default:
- *mem_type = 0; // not use memory machanism
- break;
- }
- }
- void stf_v4l2_open(V4l2Param_t *param, char *device_name)
- {
- struct stat st;
- //struct v4l2_capability cap;
- LOG(STF_LEVEL_TRACE, "Enter\n");
- // stat file
- if (-1 == stat(device_name, &st)) {
- LOG(STF_LEVEL_ERR, "Cannot identify '%s': %d, %s\n", device_name, errno, strerror(errno));
- exit(EXIT_FAILURE);
- }
- // check if is device
- if (!S_ISCHR(st.st_mode)) {
- LOG(STF_LEVEL_ERR, "%s is no device\n", device_name);
- exit(EXIT_FAILURE);
- }
- // open device
- param->fd = v4l2_open(device_name, O_RDWR /* required */ | O_NONBLOCK, 0);
- // param->fd = v4l2_open(device_name, O_RDWR, 0);
- if (-1 == param->fd) {
- LOG(STF_LEVEL_ERR, "Cannot open '%s': %d, %s\n", device_name, errno, strerror(errno));
- exit(EXIT_FAILURE);
- }
- LOG(STF_LEVEL_TRACE, "Exit\n");
- }
- void stf_v4l2_close(V4l2Param_t *param)
- {
- LOG(STF_LEVEL_TRACE, "Enter\n");
- if (-1 == v4l2_close(param->fd)) {
- errno_exit("close");
- }
- param->fd = -1;
- LOG(STF_LEVEL_TRACE, "Exit\n");
- }
- void stf_v4l2_init(V4l2Param_t *param)
- {
- struct v4l2_capability cap;
- struct v4l2_cropcap cropcap;
- struct v4l2_crop crop;
- struct v4l2_format fmt;
- struct v4l2_streamparm frameint;
- //struct v4l2_streamparm frameget;
- unsigned int min;
- LOG(STF_LEVEL_TRACE, "Enter\n");
- // query capability
- if (-1 == xioctl(param->fd, VIDIOC_QUERYCAP, &cap)) {
- if (EINVAL == errno) {
- LOG(STF_LEVEL_ERR, "%s is no V4L2 device\n", param->device_name);
- exit(EXIT_FAILURE);
- } else {
- errno_exit("VIDIOC_QUERYCAP");
- }
- }
- if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
- LOG(STF_LEVEL_ERR, "%s is no video capture device\n", param->device_name);
- exit(EXIT_FAILURE);
- }
- switch (param->io_mthd) {
- case IO_METHOD_READ:
- if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
- LOG(STF_LEVEL_ERR, "%s does not support read i/o\n", param->device_name);
- exit(EXIT_FAILURE);
- }
- break;
- case IO_METHOD_MMAP:
- case IO_METHOD_USERPTR:
- case IO_METHOD_DMABUF:
- if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
- LOG(STF_LEVEL_ERR, "%s does not support streaming i/o\n", param->device_name);
- exit(EXIT_FAILURE);
- }
- break;
- default:
- LOG(STF_LEVEL_ERR, "%s does not specify streaming i/o\n", param->device_name);
- exit(EXIT_FAILURE);
- break;
- }
- /* Select video input, video standard and tune here. */
- CLEAR(cropcap);
- cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (0 == xioctl(param->fd, VIDIOC_CROPCAP, &cropcap)) {
- crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- crop.c = cropcap.defrect; /* reset to default */
- if (-1 == xioctl(param->fd, VIDIOC_S_CROP, &crop)) {
- switch (errno) {
- case EINVAL:
- /* Cropping not supported. */
- break;
- default:
- /* Errors ignored. */
- break;
- }
- }
- } else {
- /* Errors ignored. */
- }
- /* If the user has set the fps to -1, don't try to set the frame interval */
- if (param->fps != -1) {
- CLEAR(frameint);
- /* Attempt to set the frame interval. */
- frameint.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- frameint.parm.capture.timeperframe.numerator = 1;
- frameint.parm.capture.timeperframe.denominator = param->fps;
- if (-1 == xioctl(param->fd, VIDIOC_S_PARM, &frameint)) {
- LOG(STF_LEVEL_WARN, "Unable to set frame interval.\n");
- }
- LOG(STF_LEVEL_INFO, "set frame interval = %d.\n", frameint.parm.capture.timeperframe.denominator);
- }
- // set v4l2_format
- CLEAR(fmt);
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fmt.fmt.pix.width = param->width;
- fmt.fmt.pix.height = param->height;
- fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
- fmt.fmt.pix.pixelformat = param->format;
- if (-1 == xioctl(param->fd, VIDIOC_S_FMT, &fmt)) {
- errno_exit("VIDIOC_S_FMT");
- }
- if (param->crop_flag) {
- struct v4l2_selection sel_crop = {
- V4L2_BUF_TYPE_VIDEO_CAPTURE,
- V4L2_SEL_TGT_CROP,
- 0,
- {param->crop_info.left, param->crop_info.top,
- param->crop_info.width, param->crop_info.height} // TODO: opt here
- };
- struct v4l2_selection get_crop = {
- V4L2_BUF_TYPE_VIDEO_CAPTURE,
- V4L2_SEL_TGT_CROP,
- };
- LOG(STF_LEVEL_DEBUG, "sel_crop.left = %d, %d, %d, %d\n",
- sel_crop.r.left, sel_crop.r.top, sel_crop.r.width, sel_crop.r.height);
- if (-1 == xioctl(param->fd, VIDIOC_S_SELECTION, &sel_crop)) {
- LOG(STF_LEVEL_ERR, "S_SELECTION Failed.\n");
- }
- LOG(STF_LEVEL_DEBUG, "sel_crop.left = %d, %d, %d, %d\n",
- sel_crop.r.left, sel_crop.r.top, sel_crop.r.width, sel_crop.r.height);
- if (-1 == xioctl(param->fd, VIDIOC_G_SELECTION, &get_crop)) {
- LOG(STF_LEVEL_ERR, "G_SELECTION Failed.\n");
- }
- LOG(STF_LEVEL_DEBUG, "get_crop.left = %d, %d, %d, %d\n",
- get_crop.r.left, get_crop.r.top, get_crop.r.width, get_crop.r.height);
- if (memcmp(&sel_crop, &get_crop, sizeof(sel_crop))) {
- LOG(STF_LEVEL_WARN, "set/get selection diff.\n");
- }
- }
- // get v4l2_format
- memset(&fmt, 0, sizeof(struct v4l2_format));
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fmt.fmt.pix.field = V4L2_FIELD_ANY;
- if (-1 == ioctl(param->fd, VIDIOC_G_FMT, &fmt)) {
- errno_exit("VIDIOC_G_FMT");
- }
- LOG(STF_LEVEL_INFO, "VIDIOC_G_FMT: type=%d, Fourcc format=%c%c%c%c\n",
- fmt.type, fmt.fmt.pix.pixelformat & 0xff,
- (fmt.fmt.pix.pixelformat >> 8) &0xff,
- (fmt.fmt.pix.pixelformat >> 16) &0xff,
- (fmt.fmt.pix.pixelformat >> 24) &0xff);
- LOG(STF_LEVEL_INFO, " \t width=%d, height=%d, field=%d, bytesperline=%d, sizeimage=%d\n",
- fmt.fmt.pix.width, fmt.fmt.pix.height, fmt.fmt.pix.field,
- fmt.fmt.pix.bytesperline, fmt.fmt.pix.sizeimage);
- //if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_YUV420) {
- //if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_RGB565) {
- if (fmt.fmt.pix.pixelformat != param->format) {
- LOG(STF_LEVEL_ERR, "v4l2 didn't accept format %d. Can't proceed.\n", param->format);
- exit(EXIT_FAILURE);
- }
- /* Note VIDIOC_S_FMT may change width and height. */
- if (param->width != fmt.fmt.pix.width) {
- param->width = fmt.fmt.pix.width;
- LOG(STF_LEVEL_WARN, "Correct image width set to %i by device %s.\n", param->width, param->device_name);
- }
- if (param->height != fmt.fmt.pix.height) {
- param->height = fmt.fmt.pix.height;
- LOG(STF_LEVEL_WARN, "Correct image height set to %i by device %s.\n", param->height, param->device_name);
- }
- // TODO: who and why add the below here? Change bytesperline and sizeimage
- /* 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;
- }
- // param->image_size = fmt.fmt.pix.sizeimage; // wrong here
- LOG(STF_LEVEL_LOG, "fmt.fmt.pix.sizeimage=%d, fmt.fmt.pix.bytesperline=%d\n",
- fmt.fmt.pix.sizeimage, fmt.fmt.pix.bytesperline);
- // convert mem type
- convert_v4l2_mem_type(param->io_mthd, ¶m->mem_type);
- LOG(STF_LEVEL_TRACE, "Exit\n");
- }
- void stf_v4l2_uninit(V4l2Param_t *param)
- {
- uint32_t i;
- LOG(STF_LEVEL_TRACE, "Enter\n");
- switch (param->io_mthd) {
- case IO_METHOD_READ:
- free(param->pBuffers[0].start);
- break;
- case IO_METHOD_MMAP:
- for (i = 0; i < param->n_buffers; ++i) {
- if (-1 == v4l2_munmap(param->pBuffers[i].start,
- param->pBuffers[i].length)) {
- errno_exit("munmap");
- }
- }
- break;
- case IO_METHOD_USERPTR:
- for (i = 0; i < param->n_buffers; ++i) {
- free(param->pBuffers[i].start);
- }
- break;
- case IO_METHOD_DMABUF:
- break;
- default:
- break;
- }
- free(param->pBuffers);
- LOG(STF_LEVEL_TRACE, "Exit\n");
- }
- static void stf_v4l2_readInit(V4l2Param_t *param)
- {
- LOG(STF_LEVEL_TRACE, "Enter\n");
- param->n_buffers = 1;
- param->pBuffers = calloc(param->n_buffers, sizeof(*param->pBuffers));
- if (!param->pBuffers) {
- LOG(STF_LEVEL_ERR, "Out of memory\n");
- exit(EXIT_FAILURE);
- }
- param->pBuffers[0].length = param->image_size;
- param->pBuffers[0].start = malloc(param->image_size);
- if (!param->pBuffers[0].start) {
- LOG(STF_LEVEL_ERR, "Out of memory\n");
- exit(EXIT_FAILURE);
- }
- LOG(STF_LEVEL_TRACE, "Exit\n");
- }
- static void stf_v4l2_mmapInit(V4l2Param_t *param)
- {
- int i = 0;
- struct v4l2_requestbuffers req;
- CLEAR(req);
- LOG(STF_LEVEL_TRACE, "Enter\n");
- req.count = BUFCOUNT;
- req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- req.memory = V4L2_MEMORY_MMAP;
- if (-1 == xioctl(param->fd, VIDIOC_REQBUFS, &req)) {
- if (EINVAL == errno) {
- LOG(STF_LEVEL_ERR, "%s does not support memory mapping\n", param->device_name);
- exit(EXIT_FAILURE);
- } else {
- errno_exit("VIDIOC_REQBUFS");
- }
- }
- if (req.count < 2) {
- LOG(STF_LEVEL_ERR, "Insufficient buffer memory on %s\n", param->device_name);
- exit(EXIT_FAILURE);
- }
- param->n_buffers = req.count;
- param->pBuffers = calloc(param->n_buffers, sizeof(*param->pBuffers));
- if (!param->pBuffers) {
- LOG(STF_LEVEL_ERR, "Out of memory\n");
- exit(EXIT_FAILURE);
- }
- for (i = 0; i < param->n_buffers; ++i) {
- struct v4l2_buffer buf;
- CLEAR(buf);
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- buf.index = i;
- if (-1 == xioctl(param->fd, VIDIOC_QUERYBUF, &buf))
- errno_exit("VIDIOC_QUERYBUF");
- param->pBuffers[i].length = buf.length;
- param->pBuffers[i].start = v4l2_mmap(NULL, /* start anywhere */
- buf.length, PROT_READ | PROT_WRITE, /* required */
- MAP_SHARED, /* recommended */
- param->fd, buf.m.offset);
- if (MAP_FAILED == param->pBuffers[i].start) {
- errno_exit("mmap");
- }
- param->image_size = buf.length; // NOTE: updated value
- }
- LOG(STF_LEVEL_TRACE, "Exit\n");
- }
- static void stf_v4l2_dmabufInit(V4l2Param_t *param, int *dmabufs, int count)
- {
- int i = 0;
- struct v4l2_requestbuffers req;
- LOG(STF_LEVEL_TRACE, "Enter\n");
- CLEAR(req);
- req.count = BUFCOUNT; // TODO: modify later
- req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- req.memory = V4L2_MEMORY_DMABUF;
- if (-1 == xioctl(param->fd, VIDIOC_REQBUFS, &req)) {
- if (EINVAL == errno) {
- fprintf(stderr, "does not support dmabuf\n");
- exit(EXIT_FAILURE);
- } else {
- errno_print("VIDIOC_REQBUFS");
- }
- }
- if (req.count < 2) {
- fprintf(stderr, "Insufficient buffer memory\n");
- exit(EXIT_FAILURE);
- }
- param->n_buffers = req.count;
- param->pBuffers = calloc(param->n_buffers, sizeof(*param->pBuffers));
- if (!param->pBuffers) {
- LOG(STF_LEVEL_ERR, "Out of memory\n");
- exit(EXIT_FAILURE);
- }
- for (i = 0; i < req.count; ++i) {
- struct v4l2_buffer buf;
- CLEAR(buf);
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_DMABUF;
- buf.index = i;
- if (-1 == xioctl(param->fd, VIDIOC_QUERYBUF, &buf)) {
- errno_print("VIDIOC_QUERYBUF");
- }
- param->pBuffers[i].index = buf.index;
- param->pBuffers[i].dmabuf_fd = dmabufs[i];
- #if 0
- param->pBuffers[i].length = buf.length;
- param->pBuffers[i].start = mmap(NULL /* start anywhere */,
- buf.length,
- PROT_READ | PROT_WRITE /* required */,
- MAP_SHARED /* recommended */,
- dmabufs[i], 0);
- if (MAP_FAILED == param->pBuffers[i].start)
- errno_print("mmap");
- #endif
- }
- LOG(STF_LEVEL_TRACE, "Exit\n");
- }
- static void stf_v4l2_userptrInit(V4l2Param_t *param)
- {
- struct v4l2_requestbuffers req;
- unsigned int page_size;
- unsigned int buffer_size = param->image_size;
- int i = 0;
- page_size = getpagesize();
- buffer_size = (buffer_size + page_size - 1) & ~(page_size - 1);
- CLEAR(req);
- req.count = BUFCOUNT;
- req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- req.memory = V4L2_MEMORY_USERPTR;
- if (-1 == xioctl(param->fd, VIDIOC_REQBUFS, &req)) {
- if (EINVAL == errno) {
- LOG(STF_LEVEL_ERR, "%s does not support user pointer i/o\n", param->device_name);
- exit(EXIT_FAILURE);
- } else {
- errno_exit("VIDIOC_REQBUFS");
- }
- }
- param->n_buffers = 4;
- param->pBuffers = calloc(param->n_buffers, sizeof(*param->pBuffers));
- if (!param->pBuffers) {
- LOG(STF_LEVEL_ERR, "Out of memory\n");
- exit(EXIT_FAILURE);
- }
- for (i = 0; i < param->n_buffers; ++i) {
- param->pBuffers[i].length = buffer_size;
- param->pBuffers[i].start = memalign(/* boundary */ page_size, buffer_size);
- if (!param->pBuffers[i].start) {
- LOG(STF_LEVEL_ERR, "Out of memory\n");
- exit(EXIT_FAILURE);
- }
- }
- param->image_size = buffer_size;
- }
- void sft_v4l2_prepare_capturing(V4l2Param_t *param, int *dmabufs, int count)
- {
- LOG(STF_LEVEL_TRACE, "Enter\n");
- switch (param->io_mthd) {
- case IO_METHOD_READ:
- stf_v4l2_readInit(param);
- break;
- case IO_METHOD_MMAP:
- stf_v4l2_mmapInit(param);
- break;
- case IO_METHOD_USERPTR:
- stf_v4l2_userptrInit(param);
- break;
- case IO_METHOD_DMABUF:
- stf_v4l2_dmabufInit(param, dmabufs, count);
- break;
- default:
- LOG(STF_LEVEL_ERR, "%s does not specify streaming i/o\n", param->device_name);
- exit(EXIT_FAILURE);
- break;
- }
- LOG(STF_LEVEL_TRACE, "Exit\n");
- }
- void sft_v4l2_start_capturing(V4l2Param_t *param)
- {
- unsigned int i;
- enum v4l2_buf_type type;
- LOG(STF_LEVEL_TRACE, "Enter\n");
- switch (param->io_mthd) {
- case IO_METHOD_READ:
- /* Nothing to do. */
- break;
- case IO_METHOD_MMAP:
- case IO_METHOD_USERPTR:
- case IO_METHOD_DMABUF:
- for (i = 0; i < param->n_buffers; ++i) {
- stf_v4l2_queue_buffer(param, i);
- }
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (-1 == xioctl(param->fd, VIDIOC_STREAMON, &type)) {
- errno_exit("VIDIOC_STREAMON");
- }
- break;
- default:
- break;
- }
- LOG(STF_LEVEL_TRACE, "Exit\n");
- }
- void stf_v4l2_stop_capturing(V4l2Param_t *param)
- {
- enum v4l2_buf_type type;
- LOG(STF_LEVEL_TRACE, "Enter\n");
- switch (param->io_mthd) {
- case IO_METHOD_READ:
- /* Nothing to do. */
- break;
- case IO_METHOD_MMAP:
- case IO_METHOD_USERPTR:
- case IO_METHOD_DMABUF:
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (-1 == xioctl(param->fd, VIDIOC_STREAMOFF, &type))
- errno_exit("VIDIOC_STREAMOFF");
- break;
- default:
- break;
- }
- LOG(STF_LEVEL_TRACE, "Exit\n");
- }
- // support V4L2_MEMORY_MMAP / V4L2_MEMORY_USERPTR / V4L2_MEMORY_DMABUF
- // NOTE: for V4L2_MEMORY_USERPTR, index is pBuffers index
- void stf_v4l2_queue_buffer(V4l2Param_t *param, int index)
- {
- struct v4l2_buffer buf;
- LOG(STF_LEVEL_TRACE, "Enter\n");
- assert(index < param->n_buffers);
- CLEAR(buf);
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = param->mem_type;
- buf.index = index; // NOTE: for V4L2_MEMORY_USERPTR not used here?
- if (param->mem_type == V4L2_MEMORY_DMABUF) {
- //buf.m.fd = param->dmabuf_fd;
- buf.m.fd = param->pBuffers[index].dmabuf_fd;
- } else if (param->mem_type == V4L2_MEMORY_USERPTR) {
- buf.m.userptr = (unsigned long)param->pBuffers[index].start;
- buf.length = param->pBuffers[index].length;
- }
- if (-1 == xioctl(param->fd, VIDIOC_QBUF, &buf)) {
- errno_print("VIDIOC_QBUF");
- }
- LOG(STF_LEVEL_TRACE, "Exit\n");
- }
- // support V4L2_MEMORY_MMAP / V4L2_MEMORY_USERPTR / V4L2_MEMORY_DMABUF
- int stf_v4l2_dequeue_buffer(V4l2Param_t *param, struct v4l2_buffer *buf)
- {
- int index = 0;
- LOG(STF_LEVEL_TRACE, "Enter\n");
- PCLEAR(buf);
- buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf->memory = param->mem_type;
- if (-1 == xioctl(param->fd, VIDIOC_DQBUF, buf)) {
- switch (errno) {
- case EAGAIN:
- return 0;
- case EIO:
- /* Could ignore EIO, see spec. */
- /* fall through */
- default:
- errno_print("VIDIOC_DQBUF");
- }
- }
- index = buf->index;
- if (param->mem_type == V4L2_MEMORY_USERPTR) {
- for (index = 0; index < param->n_buffers; ++index) {
- if (buf->m.userptr == (unsigned long)param->pBuffers[index].start
- && buf->length == param->pBuffers[index].length) {
- break;
- }
- }
- }
- assert(index < param->n_buffers);
- LOG(STF_LEVEL_TRACE, "Exit\n");
- return 1;
- }
|