예제 #1
0
파일: v4l2uvc.c 프로젝트: coolpds/voxel
static int init_v4l2(struct vdIn *vd)
{
    int i;
    int ret = 0;
    if((vd->fd = OPEN_VIDEO(vd->videodevice, O_RDWR)) == -1) {
        perror("ERROR opening V4L interface");
        DBG("errno: %d", errno);
        return -1;
    }

    memset(&vd->cap, 0, sizeof(struct v4l2_capability));
    ret = xioctl(vd->fd, VIDIOC_QUERYCAP, &vd->cap);
    if(ret < 0) {
        fprintf(stderr, "Error opening device %s: unable to query device.\n", vd->videodevice);
        goto fatal;
    }

    if((vd->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
        fprintf(stderr, "Error opening device %s: video capture not supported.\n",
                vd->videodevice);
        goto fatal;;
    }

    if(vd->grabmethod) {
        if(!(vd->cap.capabilities & V4L2_CAP_STREAMING)) {
            fprintf(stderr, "%s does not support streaming i/o\n", vd->videodevice);
            goto fatal;
        }
    } else {
        if(!(vd->cap.capabilities & V4L2_CAP_READWRITE)) {
            fprintf(stderr, "%s does not support read i/o\n", vd->videodevice);
            goto fatal;
        }
    }

    if (vd->vstd != V4L2_STD_UNKNOWN) {
        if (ioctl(vd->fd, VIDIOC_S_STD, &vd->vstd) == -1) {
            fprintf(stderr, "Can't set video standard: %s\n",strerror(errno));
            goto fatal;
        }
    }

    /*
     * set format in
     */
    memset(&vd->fmt, 0, sizeof(struct v4l2_format));
    vd->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    vd->fmt.fmt.pix.width = vd->width;
    vd->fmt.fmt.pix.height = vd->height;
    vd->fmt.fmt.pix.pixelformat = vd->formatIn;
    vd->fmt.fmt.pix.field = V4L2_FIELD_ANY;
    ret = xioctl(vd->fd, VIDIOC_S_FMT, &vd->fmt);
    if(ret < 0) {
        fprintf(stderr, "Unable to set format: %d res: %dx%d\n", vd->formatIn, vd->width, vd->height);
        goto fatal;
    }

    if((vd->fmt.fmt.pix.width != vd->width) ||
            (vd->fmt.fmt.pix.height != vd->height)) {
        fprintf(stderr, "i: The format asked unavailable, so the width %d height %d \n", vd->fmt.fmt.pix.width, vd->fmt.fmt.pix.height);
        vd->width = vd->fmt.fmt.pix.width;
        vd->height = vd->fmt.fmt.pix.height;
        /*
         * look the format is not part of the deal ???
         */
        if(vd->formatIn != vd->fmt.fmt.pix.pixelformat) {
            if(vd->formatIn == V4L2_PIX_FMT_MJPEG) {
                fprintf(stderr, "The input device does not supports MJPEG mode\n"
                                "You may also try the YUV mode (-yuv option), \n"
                                "or the you can set another supported formats using the -fourcc argument.\n"
                                "Note: streaming using uncompressed formats will require much more CPU power on your server\n");
                goto fatal;
            } else if(vd->formatIn == V4L2_PIX_FMT_YUYV) {
                fprintf(stderr, "The input device does not supports YUV format\n");
                goto fatal;
            } else if (vd->formatIn == V4L2_PIX_FMT_RGB565) {
                fprintf(stderr, "The input device does not supports RGB565 format\n");
                goto fatal;
            }
        } else {
            vd->formatIn = vd->fmt.fmt.pix.pixelformat;
        }
    }

    /*
     * set framerate
     */

    if (vd->fps != -1) {
        struct v4l2_streamparm *setfps;
        setfps = (struct v4l2_streamparm *) calloc(1, sizeof(struct v4l2_streamparm));
        memset(setfps, 0, sizeof(struct v4l2_streamparm));
        setfps->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

        /*
        * first query streaming parameters to determine that the FPS selection is supported
        */
        ret = xioctl(vd->fd, VIDIOC_G_PARM, setfps);
        if (ret == 0) {
            if (setfps->parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
                memset(setfps, 0, sizeof(struct v4l2_streamparm));
                setfps->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                setfps->parm.capture.timeperframe.numerator = 1;
                setfps->parm.capture.timeperframe.denominator = vd->fps==-1?255:vd->fps; // if no default fps set set it to maximum

                ret = xioctl(vd->fd, VIDIOC_S_PARM, setfps);
                if (ret) {
                    perror("Unable to set the FPS\n");
                } else {
                    if (vd->fps != setfps->parm.capture.timeperframe.denominator) {
                        IPRINT("FPS coerced ......: from %d to %d\n", vd->fps, setfps->parm.capture.timeperframe.denominator);
                    }

                    // if we selecting lower FPS than the allowed then we will use software framedropping
                    if (vd->fps < setfps->parm.capture.timeperframe.denominator) {
                        vd->soft_framedrop = 1;
                        vd->frame_period_time = 1000/vd->fps; // calcualate frame period time in ms
                        IPRINT("Frame period time ......: %ld ms\n", vd->frame_period_time);

                        // set FPS to maximum in order to minimize the lagging
                        memset(setfps, 0, sizeof(struct v4l2_streamparm));
                        setfps->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
                        setfps->parm.capture.timeperframe.numerator = 1;
                        setfps->parm.capture.timeperframe.denominator = 255;
                        ret = xioctl(vd->fd, VIDIOC_S_PARM, setfps);
                        if (ret) {
                            perror("Unable to set the FPS\n");
                        }
                    }
                }
            } else {
                perror("Setting FPS on the capture device is not supported, fallback to software framedropping\n");
                vd->soft_framedrop = 1;
                vd->frame_period_time = 1000/vd->fps; // calcualate frame period time in ms
                IPRINT("Frame period time ......: %ld ms\n", vd->frame_period_time);
            }
        } else {
            perror("Unable to query that the FPS change is supported\n");
        }
    }

    /*
     * request buffers
     */
    memset(&vd->rb, 0, sizeof(struct v4l2_requestbuffers));
    vd->rb.count = NB_BUFFER;
    vd->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    vd->rb.memory = V4L2_MEMORY_MMAP;

    ret = xioctl(vd->fd, VIDIOC_REQBUFS, &vd->rb);
    if(ret < 0) {
        perror("Unable to allocate buffers");
        goto fatal;
    }

    /*
     * map the buffers
     */
    for(i = 0; i < NB_BUFFER; i++) {
        memset(&vd->buf, 0, sizeof(struct v4l2_buffer));
        vd->buf.index = i;
        vd->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        vd->buf.memory = V4L2_MEMORY_MMAP;
        ret = xioctl(vd->fd, VIDIOC_QUERYBUF, &vd->buf);
        if(ret < 0) {
            perror("Unable to query buffer");
            goto fatal;
        }

        if(debug)
            fprintf(stderr, "length: %u offset: %u\n", vd->buf.length, vd->buf.m.offset);

        vd->mem[i] = mmap(0 /* start anywhere */ ,
                          vd->buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, vd->fd,
                          vd->buf.m.offset);
        if(vd->mem[i] == MAP_FAILED) {
            perror("Unable to map buffer");
            goto fatal;
        }
        if(debug)
            fprintf(stderr, "Buffer mapped at address %p.\n", vd->mem[i]);
    }

    /*
     * Queue the buffers.
     */
    for(i = 0; i < NB_BUFFER; ++i) {
        memset(&vd->buf, 0, sizeof(struct v4l2_buffer));
        vd->buf.index = i;
        vd->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        vd->buf.memory = V4L2_MEMORY_MMAP;
        ret = xioctl(vd->fd, VIDIOC_QBUF, &vd->buf);
        if(ret < 0) {
            perror("Unable to queue buffer");
            goto fatal;;
        }
    }
    return 0;
fatal:
    return -1;

}
예제 #2
0
static int init_v4l2(struct vdIn *vd)
{
    int i;
    int ret = 0;
    if((vd->fd = OPEN_VIDEO(vd->videodevice, O_RDWR)) == -1) {
        perror("ERROR opening V4L interface");
        DBG("errno: %d", errno);
        return -1;
    }

    memset(&vd->cap, 0, sizeof(struct v4l2_capability));
    ret = xioctl(vd->fd, VIDIOC_QUERYCAP, &vd->cap);
    if(ret < 0) {
        fprintf(stderr, "Error opening device %s: unable to query device.\n", vd->videodevice);
        goto fatal;
    }

    if((vd->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
        fprintf(stderr, "Error opening device %s: video capture not supported.\n",
                vd->videodevice);
        goto fatal;;
    }

    if(vd->grabmethod) {
        if(!(vd->cap.capabilities & V4L2_CAP_STREAMING)) {
            fprintf(stderr, "%s does not support streaming i/o\n", vd->videodevice);
            goto fatal;
        }
    } else {
        if(!(vd->cap.capabilities & V4L2_CAP_READWRITE)) {
            fprintf(stderr, "%s does not support read i/o\n", vd->videodevice);
            goto fatal;
        }
    }

    /*
     * set format in
     */
    memset(&vd->fmt, 0, sizeof(struct v4l2_format));
    vd->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    vd->fmt.fmt.pix.width = vd->width;
    vd->fmt.fmt.pix.height = vd->height;
    vd->fmt.fmt.pix.pixelformat = vd->formatIn;
    vd->fmt.fmt.pix.field = V4L2_FIELD_ANY;
    ret = xioctl(vd->fd, VIDIOC_S_FMT, &vd->fmt);
    if(ret < 0) {
        fprintf(stderr, "Unable to set format: %d res: %dx%d\n", vd->formatIn, vd->width, vd->height);
        goto fatal;
    }

    if((vd->fmt.fmt.pix.width != vd->width) ||
            (vd->fmt.fmt.pix.height != vd->height)) {
        fprintf(stderr, "i: The format asked unavailable, so the width %d height %d \n", vd->fmt.fmt.pix.width, vd->fmt.fmt.pix.height);
        vd->width = vd->fmt.fmt.pix.width;
        vd->height = vd->fmt.fmt.pix.height;
        /*
         * look the format is not part of the deal ???
         */
        if(vd->formatIn != vd->fmt.fmt.pix.pixelformat) {
            if(vd->formatIn == V4L2_PIX_FMT_MJPEG) {
                fprintf(stderr, "The inpout device does not supports MJPEG mode\nYou may also try the YUV mode (-yuv option), but it requires a much more CPU power\n");
                goto fatal;
            } else if(vd->formatIn == V4L2_PIX_FMT_YUYV) {
                fprintf(stderr, "The input device does not supports YUV mode\n");
                goto fatal;
            }
        } else {
            vd->formatIn = vd->fmt.fmt.pix.pixelformat;
        }
    }

    /*
     * set framerate
     */
    struct v4l2_streamparm *setfps;
    setfps = (struct v4l2_streamparm *) calloc(1, sizeof(struct v4l2_streamparm));
    memset(setfps, 0, sizeof(struct v4l2_streamparm));
    setfps->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    setfps->parm.capture.timeperframe.numerator = 1;
    setfps->parm.capture.timeperframe.denominator = vd->fps;
    ret = xioctl(vd->fd, VIDIOC_S_PARM, setfps);

    /*
     * request buffers
     */
    memset(&vd->rb, 0, sizeof(struct v4l2_requestbuffers));
    vd->rb.count = NB_BUFFER;
    vd->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    vd->rb.memory = V4L2_MEMORY_MMAP;

    ret = xioctl(vd->fd, VIDIOC_REQBUFS, &vd->rb);
    if(ret < 0) {
        perror("Unable to allocate buffers");
        goto fatal;
    }

    /*
     * map the buffers
     */
    for(i = 0; i < NB_BUFFER; i++) {
        memset(&vd->buf, 0, sizeof(struct v4l2_buffer));
        vd->buf.index = i;
        vd->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        vd->buf.memory = V4L2_MEMORY_MMAP;
        ret = xioctl(vd->fd, VIDIOC_QUERYBUF, &vd->buf);
        if(ret < 0) {
            perror("Unable to query buffer");
            goto fatal;
        }

        if(debug)
            fprintf(stderr, "length: %u offset: %u\n", vd->buf.length, vd->buf.m.offset);

        vd->mem[i] = mmap(0 /* start anywhere */ ,
                          vd->buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, vd->fd,
                          vd->buf.m.offset);
        if(vd->mem[i] == MAP_FAILED) {
            perror("Unable to map buffer");
            goto fatal;
        }
        if(debug)
            fprintf(stderr, "Buffer mapped at address %p.\n", vd->mem[i]);
    }

    /*
     * Queue the buffers.
     */
    for(i = 0; i < NB_BUFFER; ++i) {
        memset(&vd->buf, 0, sizeof(struct v4l2_buffer));
        vd->buf.index = i;
        vd->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        vd->buf.memory = V4L2_MEMORY_MMAP;
        ret = xioctl(vd->fd, VIDIOC_QBUF, &vd->buf);
        if(ret < 0) {
            perror("Unable to queue buffer");
            goto fatal;;
        }
    }
    return 0;
fatal:
    return -1;

}
예제 #3
0
int init_v4l2(struct video_device *vd) {
    int i;
    struct v4l2_streamparm setfps;

    if ((vd->fd = OPEN_VIDEO(vd->device_filename, O_RDWR)) == -1) {
        log_itf(LOG_ERROR, "Error opening V4L2 interface on %s. errno %d", vd->device_filename, errno);
    }

    memset(&vd->cap, 0, sizeof(struct v4l2_capability));

    if (xioctl(vd->fd, VIDIOC_QUERYCAP, &vd->cap) < 0) {
        log_itf(LOG_ERROR, "Error opening device %s: unable to query device.", vd->device_filename);
        return -1;
    }

    if ((vd->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) {
        log_itf(LOG_ERROR, "Error opening device %s: video capture not supported.", vd->device_filename);
        return -1;
    }

    if (vd->use_streaming) {
        if (!(vd->cap.capabilities & V4L2_CAP_STREAMING)) {
            log_itf(LOG_ERROR, "%s does not support streaming I/O", vd->device_filename);
            return -1;
        }
    }
    else {
        if (!(vd->cap.capabilities & V4L2_CAP_READWRITE)) {
            log_itf(LOG_ERROR, "%s does not support read I/O", vd->device_filename);
            return -1;
        }
    }

    vd->streaming_state = STREAMING_OFF;

    // set format in
    memset(&vd->fmt, 0, sizeof(struct v4l2_format));
    vd->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    vd->fmt.fmt.pix.width = vd->width;
    vd->fmt.fmt.pix.height = vd->height;
    vd->fmt.fmt.pix.pixelformat = vd->format_in;
    vd->fmt.fmt.pix.field = V4L2_FIELD_ANY;

    if (xioctl(vd->fd, VIDIOC_S_FMT, &vd->fmt) < 0) {
        log_itf(LOG_WARNING, "Unable to set format %d, res %dx%d, device %s. Trying fallback.", vd->format_in, vd->width, vd->height, vd->device_filename);

        // Try the fallback format
        vd->format_in = UVC_FALLBACK_FORMAT;
        vd->fmt.fmt.pix.pixelformat = vd->format_in;

        if (xioctl(vd->fd, VIDIOC_S_FMT, &vd->fmt) < 0) {
            log_itf(LOG_ERROR, "Unable to set fallback format %d, res %dx%d, device %s.", vd->format_in, vd->width, vd->height, vd->device_filename);
            return -1;
        }
    }

    if ((vd->fmt.fmt.pix.width != vd->width) ||
            (vd->fmt.fmt.pix.height != vd->height)) {
        log_itf(LOG_WARNING, "The format asked unavailable, so the width %d height %d on device %s.", vd->fmt.fmt.pix.width, vd->fmt.fmt.pix.height, vd->device_filename);

        vd->width = vd->fmt.fmt.pix.width;
        vd->height = vd->fmt.fmt.pix.height;

        // look the format is not part of the deal ???
        if (vd->format_in != vd->fmt.fmt.pix.pixelformat) {
            if (vd->format_in == V4L2_PIX_FMT_MJPEG) {
                log_itf(LOG_ERROR, "The input device %s does not supports MJPEG mode.\nYou may also try the YUV mode, but it requires a much more CPU power.", vd->device_filename);
                return -1;
            } else if (vd->format_in == V4L2_PIX_FMT_YUYV) {
                log_itf(LOG_ERROR, "The input device %s does not supports YUV mode.", vd->device_filename);
                return -1;
            }
        } else {
            vd->format_in = vd->fmt.fmt.pix.pixelformat;
        }
    }

    // set framerate
    memset(&setfps, 0, sizeof(struct v4l2_streamparm));
    setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    setfps.parm.capture.timeperframe.numerator = 1;
    setfps.parm.capture.timeperframe.denominator = vd->fps;

    if (xioctl(vd->fd, VIDIOC_S_PARM, &setfps) < 0) {
        log_itf(LOG_ERROR, "Unable to set FPS to %d on device %s.", vd->fps, vd->device_filename);
        return -1;
    }


    // request buffers
    memset(&vd->rb, 0, sizeof(struct v4l2_requestbuffers));
    vd->rb.count = NB_BUFFER;
    vd->rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    vd->rb.memory = V4L2_MEMORY_MMAP;

    if (xioctl(vd->fd, VIDIOC_REQBUFS, &vd->rb) < 0) {
        log_itf(LOG_ERROR, "Unable to allocate buffers for device %s.", vd->device_filename);
        return -1;
    }

    // map the buffers
    for(i = 0; i < NB_BUFFER; i++) {
        memset(&vd->buf, 0, sizeof(struct v4l2_buffer));
        vd->buf.index = i;
        vd->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        vd->buf.memory = V4L2_MEMORY_MMAP;
        if (xioctl(vd->fd, VIDIOC_QUERYBUF, &vd->buf)) {
            log_itf(LOG_ERROR, "Unable to query buffer on device %s.", vd->device_filename);
            return -1;
        }

        vd->mem[i] = mmap(0 /* start anywhere */ ,
                          vd->buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, vd->fd,
                          vd->buf.m.offset);
        if (vd->mem[i] == MAP_FAILED) {
            log_itf(LOG_ERROR, "Unable to map buffer on device %s.", vd->device_filename);
            return -1;
        }

        DBG("Buffer mapped at address %p for device %s.", vd->mem[i], vd->device_filename);
    }

    // Queue the buffers.
    for(i = 0; i < NB_BUFFER; ++i) {
        memset(&vd->buf, 0, sizeof(struct v4l2_buffer));
        vd->buf.index = i;
        vd->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        vd->buf.memory = V4L2_MEMORY_MMAP;

        if (xioctl(vd->fd, VIDIOC_QBUF, &vd->buf) < 0) {
            log_itf(LOG_ERROR, "Unable to query buffer on device %s.", vd->device_filename);
            return -1;
        }
    }

    if (video_enable(vd)) {
        log_itf(LOG_ERROR, "Unable to enable video for device %s.", vd->device_filename);
        return -1;
    }

    return 0;
}