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

📄 video.c

📁 基于嵌入式linux的程序
💻 C
📖 第 1 页 / 共 2 页
字号:
                                                       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("Capture buffer %d mapped to address %#lx\n", numBufs,            (unsigned long) 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));    }    if (close(fd) == -1) {        ERR("Failed to close capture device (%s)\n", strerror(errno));    }    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);}/****************************************************************************** * videoThrFxn ******************************************************************************/void *videoThrFxn(void *arg){    BufferElement      flush         = { DISPLAY_FLUSH };    OutBufferElement   outFlush      = { WRITER_FLUSH };    Engine_Handle      hEngine       = NULL;    unsigned int       initMask      = 0;    VideoEnv          *envp          = (VideoEnv *) arg;    void              *status        = THREAD_SUCCESS;    int                inputFd       = 0;    char              *encodedBuffers[IO_BUFFERS];    pthread_t          displayThread;    pthread_t          writerThread;    struct v4l2_buffer v4l2buf;    struct sched_param schedParam;    DisplayEnv         displayEnv;    WriterEnv          writerEnv;    int                imageSize;    int                bufIdx;    unsigned int       numVidBufs;    VideoBuffer       *vidBufs;    VIDENC_Handle      hEncode;    pthread_attr_t     attr;    OutBufferElement   oe;    BufferElement      e;    void              *ret;    imageSize = envp->imageWidth * envp->imageHeight * SCREEN_BPP / 8;    /* Open the display input fifo */    if (FifoUtil_open(&displayEnv.inFifo,                      sizeof(BufferElement)) == FIFOUTIL_FAILURE) {        ERR("Failed to open input fifo\n");        cleanup(THREAD_FAILURE);    }    initMask |= INFIFODISPLAYOPENED;    /* Open the display output fifo */    if (FifoUtil_open(&displayEnv.outFifo,                      sizeof(BufferElement)) == FIFOUTIL_FAILURE) {        ERR("Failed to open output fifo\n");        cleanup(THREAD_FAILURE);    }    initMask |= OUTFIFODISPLAYOPENED;    /* Initialize the priming synchronization mutex */    pthread_mutex_init(&displayEnv.prime, NULL);    /* Initialize the thread attributes */    if (pthread_attr_init(&attr)) {        ERR("Failed to initialize thread attrs\n");        cleanup(THREAD_FAILURE);    }    /* Force the thread to use custom scheduling attributes */    if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED)) {        ERR("Failed to set schedule inheritance attribute\n");        cleanup(THREAD_FAILURE);    }    /* Set the thread to be fifo real time scheduled */    if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO)) {        ERR("Failed to set FIFO scheduling policy\n");        cleanup(THREAD_FAILURE);    }    /* Set the thread priority */    schedParam.sched_priority = sched_get_priority_max(SCHED_FIFO);    if (pthread_attr_setschedparam(&attr, &schedParam)) {        ERR("Failed to set scheduler parameters\n");        cleanup(THREAD_FAILURE);    }    /* Create the display thread */    displayEnv.hRendezvous = envp->hRendezvous;    if (pthread_create(&displayThread, &attr, displayThrFxn, &displayEnv)) {        ERR("Failed to create display thread\n");        cleanup(THREAD_FAILURE);    }    initMask |= DISPLAYTHREADCREATED;    DBG("Display thread created\n");    /* Open the writer input fifo */    if (FifoUtil_open(&writerEnv.inFifo,                      sizeof(OutBufferElement)) == FIFOUTIL_FAILURE) {        ERR("Failed to open input writer fifo\n");        cleanup(THREAD_FAILURE);    }    initMask |= INFIFOWRITEROPENED;    /* Open the writer output fifo */    if (FifoUtil_open(&writerEnv.outFifo,                      sizeof(OutBufferElement)) == FIFOUTIL_FAILURE) {        ERR("Failed to open output writer fifo\n");        cleanup(THREAD_FAILURE);    }    initMask |= OUTFIFOWRITEROPENED;    /* Set the thread priority */    schedParam.sched_priority = sched_get_priority_max(SCHED_FIFO) - 1;    if (pthread_attr_setschedparam(&attr, &schedParam)) {        ERR("Failed to set scheduler parameters\n");        cleanup(THREAD_FAILURE);    }    /* Create the writer thread */    writerEnv.hRendezvous = envp->hRendezvous;    writerEnv.videoFile = envp->videoFile;    if (pthread_create(&writerThread, &attr, writerThrFxn, &writerEnv)) {        ERR("Failed to create writer thread\n");        cleanup(THREAD_FAILURE);    }    initMask |= WRITERTHREADCREATED;    DBG("Writer thread created\n");    /* Initialize the video capture device */    inputFd = initCaptureDevice(&vidBufs, &numVidBufs, envp->svideoInput,                                envp->imageWidth, envp->imageHeight);    if (inputFd == FAILURE) {        cleanup(THREAD_FAILURE);    }    DBG("Video capture initialized and started\n");    initMask |= CAPTUREDEVICEINITIALIZED;    /* Reset, load, and start DSP Engine */    hEngine = Engine_open(ENGINE_NAME, NULL, NULL);    if (hEngine == NULL) {        ERR("Failed to open codec engine %s\n", ENGINE_NAME);        cleanup(THREAD_FAILURE);    }    DBG("Codec Engine opened in video thread\n");    initMask |= ENGINEOPENED;    /* Allocate and initialize video encoder on the engine */    if (videoEncodeAlgCreate(hEngine, &hEncode, envp->videoEncoder,                             envp->imageWidth, envp->imageHeight,                             envp->videoBitRate) == FAILURE) {        cleanup(THREAD_FAILURE);    }    DBG("Video encoder created\n");    initMask |= VIDEOENCODERCREATED;    /* Allocate buffers for encoded data and prime the writer thread */    for (bufIdx=0; bufIdx<IO_BUFFERS; bufIdx++) {        encodedBuffers[bufIdx] = Memory_contigAlloc(D1_FRAME_SIZE,                                                    Memory_DEFAULTALIGNMENT);            if (encodedBuffers[bufIdx] == NULL) {            ERR("Failed to allocate contiguous memory block.\n");            cleanup(THREAD_FAILURE);        }        DBG("Contiguous buffer allocated at physical address %#lx\n",            Memory_getPhysicalAddress(encodedBuffers[bufIdx]));        oe.id = WRITER_PRIME;        oe.encodedBuffer = encodedBuffers[bufIdx];        if (FifoUtil_put(&writerEnv.outFifo, &oe) == FIFOUTIL_FAILURE) {            ERR("Failed to put buffer in output fifo\n");            cleanup(THREAD_FAILURE);        }    }    initMask |= ENCODEDBUFFERSALLOCATED;    /* Signal that initialization is done and wait for other threads */    Rendezvous_meet(envp->hRendezvous);    DBG("Entering video main loop.\n");    while (!gblGetQuit()) {        if (!gblGetRecord()) {            usleep(PAUSE);            continue;        }        CLEAR(v4l2buf);        v4l2buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;        v4l2buf.memory = V4L2_MEMORY_MMAP;        /* Get a frame buffer with captured data */        if (ioctl(inputFd, VIDIOC_DQBUF, &v4l2buf) == -1) {            if (errno == EAGAIN) {                continue;            }            ERR("VIDIOC_DQBUF failed (%s)\n", strerror(errno));            breakLoop(THREAD_FAILURE);        }        e.frameBuffer = vidBufs[v4l2buf.index].start;        e.width       = envp->imageWidth;        e.height      = envp->imageHeight;        /* Display raw frame while encoding it */        if (FifoUtil_put(&displayEnv.outFifo, &e) == FIFOUTIL_FAILURE) {            ERR("Failed to put buffer in output fifo\n");            breakLoop(THREAD_FAILURE);        }        /* Get a buffer back from the writer thread */        if (FifoUtil_get(&writerEnv.inFifo, &oe) == FIFOUTIL_FAILURE) {            ERR("Failed to put buffer in output fifo\n");            breakLoop(THREAD_FAILURE);        }        /* Is the writer thread flushing the pipe? */        if (oe.id == WRITER_FLUSH) {            breakLoop(THREAD_SUCCESS);        }        /* Encode the captured video frame */        if (encodeVideoBuffer(hEncode, vidBufs[v4l2buf.index].start,                              imageSize, oe.encodedBuffer,                              &oe.frameSize) == FAILURE) {            breakLoop(THREAD_FAILURE);        }        /* Send the encoded buffer to be written to the filesystem */        if (FifoUtil_put(&writerEnv.outFifo, &oe) == FIFOUTIL_FAILURE) {            ERR("Failed to put buffer in output fifo\n");            breakLoop(THREAD_FAILURE);        }        /* Receive a buffer with a displayed frame from the display thread */        if (FifoUtil_get(&displayEnv.inFifo, &e) == FIFOUTIL_FAILURE) {                    breakLoop(THREAD_FAILURE);        }        /* Is the display thread flushing the pipe? */        if (e.id == DISPLAY_FLUSH) {            breakLoop(THREAD_SUCCESS);        }        /* Issue captured frame buffer back to device driver */        if (ioctl(inputFd, VIDIOC_QBUF, &v4l2buf) == -1) {            ERR("VIDIOC_QBUF failed (%s)\n", strerror(errno));            breakLoop(THREAD_FAILURE);        }        /* Increment statistics for OSD display */        gblIncVideoBytesEncoded(oe.frameSize);    }cleanup:    /* Make sure the other threads aren't waiting for init to complete */    Rendezvous_force(envp->hRendezvous);    /* Make sure the video thread isn't stuck in FifoUtil_get() */    FifoUtil_put(&displayEnv.outFifo, &flush);    /* Make sure the writer thread isn't stuck in FifoUtil_get() */    FifoUtil_put(&writerEnv.outFifo, &outFlush);    if (initMask & VIDEOENCODERCREATED) {        VIDENC_delete(hEncode);    }    if (initMask & ENGINEOPENED) {        Engine_close(hEngine);    }    if (initMask & CAPTUREDEVICEINITIALIZED) {        cleanupCaptureDevice(inputFd, vidBufs, numVidBufs);    }    if (initMask & WRITERTHREADCREATED) {        if (pthread_join(writerThread, &ret) == 0) {            status = ret;        }    }    if (initMask & OUTFIFOWRITEROPENED) {        FifoUtil_close(&writerEnv.outFifo);    }    if (initMask & INFIFOWRITEROPENED) {        FifoUtil_close(&writerEnv.inFifo);    }    if (initMask & DISPLAYTHREADCREATED) {        if (pthread_join(displayThread, &ret) == 0) {            status = ret;        }    }    if (initMask & OUTFIFODISPLAYOPENED) {        FifoUtil_close(&displayEnv.outFifo);    }    if (initMask & INFIFODISPLAYOPENED) {        FifoUtil_close(&displayEnv.inFifo);    }    /* Clean up the video thread */    if (initMask & ENCODEDBUFFERSALLOCATED) {        for (bufIdx=0; bufIdx<IO_BUFFERS; bufIdx++) {            Memory_contigFree(encodedBuffers[bufIdx], D1_FRAME_SIZE);        }    }    return status;}

⌨️ 快捷键说明

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