⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decode.c

📁 采集视频信号进行H264压缩并通过UDP传送
💻 C
📖 第 1 页 / 共 3 页
字号:
    enum v4l2_buf_type          type;
    int                         fd;
    int                         ret;
    VideoBuffer                *buffers;
    int                         numBufs;

    fd = open(V4L2_DEVICE, O_RDWR | O_NONBLOCK, 0);

    if (fd == -1) {
        ERR("Cannot open %s (%s)\n", V4L2_DEVICE, strerror(errno));
        return FAILURE;
    }

    /* Query for capture device capabilities */
    if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) {
        if (errno == EINVAL) {
            ERR("%s is no V4L2 device\n", V4L2_DEVICE);
            return FAILURE;
        }
        ERR("Failed VIDIOC_QUERYCAP on %s (%s)\n", V4L2_DEVICE,
            strerror(errno));
        return FAILURE;
    }

    if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
        ERR("%s is no video capture device\n", V4L2_DEVICE);
        return FAILURE;
    }

    if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
        ERR("%s does not support streaming i/o\n", V4L2_DEVICE);
        return FAILURE;
    }

    /* Select video input, video standard and tune here. */
    cropCap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    if (ioctl(fd, VIDIOC_CROPCAP, &cropCap) == -1) {
        ERR("VIDIOC_CROPCAP failed %d, %s\n", errno, strerror(errno));
        return FAILURE;
    }

    crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    crop.c = cropCap.defrect;

    if (ioctl(fd, VIDIOC_S_CROP, &crop) == -1) {
        ERR("VIDIOC_S_CROP failed %d, %s\n", errno, strerror(errno));
        return FAILURE;
    }

    /* Auto detect PAL or NTSC using the capture driver as sanity check */ 
    std = VPFE_STD_AUTO;
    if(ioctl(fd, VIDIOC_S_STD, &std) == -1) {
        ERR("VIDIOC_S_STD (auto) failed on %s (%s)\n", V4L2_DEVICE,
                                                       strerror(errno));
        return FAILURE;
    }

    do {
        ret = ioctl(fd, VIDIOC_QUERYSTD, &std);
    } while (ret == -1 && errno == EAGAIN);

    if (ret == -1) {
        ERR("VIDIOC_QUERYSTD failed on %s (%s)\n", V4L2_DEVICE,
                                                   strerror(errno));
        return FAILURE;
    }

    switch (std) {
        case V4L2_STD_NTSC:
            DBG("NTSC detected!\n");
            if (getYFactor() == PAL) {
                ERR("NTSC camera connected but PAL selected.\n");
                return FAILURE;
            }
            break;
        case V4L2_STD_PAL:
            DBG("PAL detected!\n");
            if (getYFactor() == NTSC) {
                ERR("PAL camera connected but NTSC selected.\n");
                return FAILURE;
            }
            break;
        default:
            ERR("Camera connected using unsupported video standard.\n");
            return FAILURE;
    }

    /* Use either NTSC or PAL depending on display kernel parameter */
    std = getYFactor() == NTSC ? V4L2_STD_NTSC : V4L2_STD_PAL;
    if(ioctl(fd, VIDIOC_S_STD, &std) == -1) {
        ERR("VIDIOC_S_STD failed on %s (%s)\n", V4L2_DEVICE,
                                                strerror(errno));
        return FAILURE;
    }

    /* Set the video capture image format */
    CLEAR(fmt);
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
    fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;

    if (resolution == D1) {
        *captureHeight = 480;  /* Should be D1_HEIGHT with D1 PAL support */
        *captureWidth = D1_WIDTH;
    }
    else {
        *captureHeight = CIF_HEIGHT;
        *captureWidth = CIF_WIDTH;
    }

    fmt.fmt.pix.width = *captureWidth;
    fmt.fmt.pix.height = *captureHeight;

    /* Set the video capture format */
    if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) {
        ERR("VIDIOC_S_FMT failed on %s (%s)\n", V4L2_DEVICE,
                                                strerror(errno));
        return FAILURE;
    }

    printf("Capturing %dx%d video\n", fmt.fmt.pix.width, fmt.fmt.pix.height);

    CLEAR(req);

    req.count = NUM_BUFS;
    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    req.memory = V4L2_MEMORY_MMAP;

    /* Allocate buffers inside the capture device driver */
    if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
        ERR("VIDIOC_REQBUFS failed on %s (%s)\n", V4L2_DEVICE,
                                                  strerror(errno));
        return FAILURE;
    }

    DBG("%d capture buffers were successfully allocated.\n", req.count);

    if (req.count < NUM_BUFS) {
        ERR("Insufficient buffer memory on %s\n", V4L2_DEVICE);
        return FAILURE;
    }

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

    if (!buffers) {
        ERR("Failed to allocate memory for capture buffer structs.\n");
        return FAILURE;
    }

    /* Map the allocated buffers to user space */
    for (numBufs = 0; numBufs < req.count; numBufs++) {
        CLEAR(buf);

        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        buf.index = numBufs;

        if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) {
            ERR("Failed VIDIOC_QUERYBUF on %s (%s)\n", V4L2_DEVICE,
                                                       strerror(errno));
            return FAILURE;
        }

        buffers[numBufs].length = buf.length;
        buffers[numBufs].start = mmap(NULL,
                                      buf.length,
                                      PROT_READ | PROT_WRITE,
                                      MAP_SHARED,
                                      fd, buf.m.offset);

        if (buffers[numBufs].start == MAP_FAILED) {
            ERR("Failed to mmap buffer on %s (%s)\n", V4L2_DEVICE,
                                                      strerror(errno));
            return FAILURE;
        }

        DBG("Buffer %d mmapped to %#x.\n", numBufs,
                                    (unsigned int) buffers[numBufs].start);

        if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {
            ERR("VIODIOC_QBUF failed on %s (%s)\n", V4L2_DEVICE,
                                                    strerror(errno));
            return FAILURE;
        }
    }

    /* Start the video streaming */
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;

    if (ioctl(fd, VIDIOC_STREAMON, &type) == -1) {
        ERR("VIDIOC_STREAMON failed on %s (%s)\n", V4L2_DEVICE,
                                                   strerror(errno));
        return FAILURE;
    }

    *vidBufsPtr = buffers;
    *numVidBufsPtr = numBufs;

    return fd;
}

/******************************************************************************
 * cleanupCaptureDevice
 ******************************************************************************/
static void cleanupCaptureDevice(int fd, VideoBuffer *vidBufs, int numVidBufs)
{
    enum v4l2_buf_type type;
    unsigned int       i;

    /* Shut off the video capture */
    type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (ioctl(fd, VIDIOC_STREAMOFF, &type) == -1) {
        ERR("VIDIOC_STREAMOFF failed (%s)\n", strerror(errno));
    }

    /* Unmap the capture frame buffers from user space */
    for (i = 0; i < numVidBufs; ++i) {
        if (munmap(vidBufs[i].start, vidBufs[i].length) == -1) {
            ERR("Failed to unmap capture buffer %d\n", i);
        }
    }

    free(vidBufs);

    if (close(fd) == -1) {
        ERR("Failed to close capture device (%s)\n", strerror(errno));
    }
}

/******************************************************************************
 * initDisplayDevice
 ******************************************************************************/
static int initDisplayDevice(enum Resolution resolution, char *displays[])
{
    struct fb_var_screeninfo varInfo;
    struct Zoom_Params       zoom;
    int                      fd;
    unsigned int            *buf;
    int                      i;
    int                      std;

    fd = open(FBVID_DEVICE, O_RDWR);

    if (fd == -1) {
        ERR("Failed to open fb device %s (%s)\n", FBVID_DEVICE,
                                                  strerror(errno));
        return FAILURE;
    }

    if (ioctl(fd, FBIOGET_VSCREENINFO, &varInfo) == -1) {
        ERR("Failed FBIOGET_VSCREENINFO on %s (%s)\n", FBVID_DEVICE,
                                                       strerror(errno));
        return FAILURE;
    }

    if (ioctl(fd, FBIO_GETSTD, &std) == -1) {
        ERR("Failed to get video standard from display device driver\n");
        return FAILURE;
    }

    if ((std >> 16) == 0x1) {
        setYFactor(NTSC);
    }
    else {
        setYFactor(PAL);
    }

    /* Display is always D1 */
    varInfo.xres = D1_WIDTH;
    varInfo.yres = D1_HEIGHT;
    varInfo.bits_per_pixel = SCREEN_BPP;

    if (ioctl(fd, FBIOPUT_VSCREENINFO, &varInfo) < -1) {
        ERR("Failed FBIOPUT_VSCREENINFO on %s (%s)\n", FBVID_DEVICE,
                                                       strerror(errno));
        return FAILURE;
    }

    if (varInfo.xres != D1_WIDTH ||
        varInfo.yres != D1_HEIGHT ||
        varInfo.bits_per_pixel != SCREEN_BPP) {
        ERR("Failed to get the requested screen size: %dx%d at %d bpp\n",
            D1_WIDTH, D1_HEIGHT, SCREEN_BPP);
        return FAILURE;
    }

    displays[0] = (char *) mmap (NULL,
                                 D1_FRAME_SIZE * NUM_BUFS,
                                 PROT_READ | PROT_WRITE,
                                 MAP_SHARED,
                                 fd, 0);

    /* Map the video buffer to user space */
    if (displays[0] == MAP_FAILED) {
        ERR("Failed mmap on %s (%s)\n", FBVID_DEVICE, strerror(errno));
        return FAILURE;
    }

    for (i=0; i<NUM_BUFS-1; i++) {
        displays[i+1] = displays[i] + D1_FRAME_SIZE;
    }

    /* Clear the video buffers */
    buf = (unsigned int *) displays[0];

    for (i=0; i<D1_FRAME_SIZE * NUM_BUFS / sizeof(unsigned int); i++) {
        buf[i] = UYVY_BLACK;
    }

    /* Set the display zoom factor */
    if (resolution == ZOOM) {
        zoom.WindowID = VID1_INDEX;
        zoom.Zoom_H = ZOOM_2X;
        zoom.Zoom_V = ZOOM_2X;

        if (ioctl(fd, FBIO_SETZOOM, &zoom)) {
            ERR("Failed setting zoom parameters\n");
            return FAILURE;
        }

        printf("Display set to %dx%d and 2x zoom\n",varInfo.xres, varInfo.yres);
    }
    else {
        zoom.WindowID = VID1_INDEX;
        zoom.Zoom_H = ZOOM_1X;
        zoom.Zoom_V = ZOOM_1X;

        if (ioctl(fd, FBIO_SETZOOM, &zoom)) {
            ERR("Failed setting zoom parameters\n");
            return FAILURE;
        }

        printf("Display set to %dx%d and no zoom\n",varInfo.xres, varInfo.yres);
    }

    return fd;
}

/******************************************************************************
 * cleanupDisplayDevice
 ******************************************************************************/
static void cleanupDisplayDevice(int fd, char *displays[])
{
    struct Zoom_Params zoom;

    zoom.WindowID = VID1_INDEX;
    zoom.Zoom_H = ZOOM_1X;
    zoom.Zoom_V = ZOOM_1X;

    if (ioctl(fd, FBIO_SETZOOM, &zoom)) {
        ERR("Failed setting zoom parameters\n");
    }

    munmap(displays[0], D1_FRAME_SIZE * NUM_BUFS);
    close(fd);
}

/******************************************************************************

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -