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

📄 display.c

📁 ti达芬奇开发板H.264视频解码的完整demo程序
💻 C
字号:
/* * display.c * * ============================================================================ * Copyright (c) Texas Instruments Inc 2005 * * Use of this software is controlled by the terms and conditions found in the * license agreement under which this software has been supplied or provided. * ============================================================================ *//* Standard Linux headers */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <sys/mman.h>#include <sys/ioctl.h>#include <pthread.h>#include <linux/fb.h>/* Davinci specific kernel headers */#include <video/davincifb.h>/* Demo headers */#include <rendezvous.h>#include <fifoutil.h>#include "decode.h"#include "display.h"/* Video display is triple buffered */#define NUM_BUFS                 3/* Black color in UYVY format */#define UYVY_BLACK               0x10801080/* The levels of initialization */#define DISPLAYDEVICEINITIALIZED 0x1static int waitForVsync(int fd);static int flipDisplayBuffers(int fd, int displayIdx);static int initDisplayDevice(char *displays[]);static void cleanupDisplayDevice(int fd, char *displays[]);/****************************************************************************** * waitForVsync ******************************************************************************/static int waitForVsync(int fd){    int dummy;    /* Wait for vertical sync */    if (ioctl(fd, FBIO_WAITFORVSYNC, &dummy) == -1) {        ERR("Failed FBIO_WAITFORVSYNC (%s)\n", strerror(errno));        return FAILURE;    }    return SUCCESS;}/****************************************************************************** * flipDisplayBuffers ******************************************************************************/static int flipDisplayBuffers(int fd, int displayIdx){    struct fb_var_screeninfo vInfo;    if (ioctl(fd, FBIOGET_VSCREENINFO, &vInfo) == -1) {        ERR("Failed FBIOGET_VSCREENINFO (%s)\n", strerror(errno));        return FAILURE;    }    vInfo.yoffset = vInfo.yres * displayIdx;    /* Swap the working buffer for the displayed buffer */    if (ioctl(fd, FBIOPAN_DISPLAY, &vInfo) == -1) {        ERR("Failed FBIOPAN_DISPLAY (%s)\n", strerror(errno));        return FAILURE;    }    return SUCCESS;}/****************************************************************************** * initDisplayDevice ******************************************************************************/static int initDisplayDevice(char *displays[]){    struct fb_var_screeninfo varInfo;    unsigned int            *buf;    int                      fd;    int                      i;    /* Open video display device */    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;    }    varInfo.xres = D1_WIDTH;    varInfo.yres = D1_HEIGHT;    varInfo.bits_per_pixel = SCREEN_BPP;    /* Set video display format */    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;    }    /* Map the video buffers to user space */    displays[0] = (char *) mmap (NULL,                                 D1_FRAME_SIZE * NUM_BUFS,                                 PROT_READ | PROT_WRITE,                                 MAP_SHARED,                                 fd, 0);    if (displays[0] == MAP_FAILED) {        ERR("Failed mmap on %s (%s)\n", FBVID_DEVICE, strerror(errno));        return FAILURE;    }    /* 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;    }    DBG("Display buffer %d mapped to address %#lx\n", 0,        (unsigned long) displays[0]);    for (i=0; i<NUM_BUFS-1; i++) {        displays[i+1] = displays[i] + D1_FRAME_SIZE;        DBG("Display buffer %d mapped to address %#lx\n", i+1,            (unsigned long) displays[i+1]);    }    return fd;}/****************************************************************************** * cleanupDisplayDevice ******************************************************************************/static void cleanupDisplayDevice(int fd, char *displays[]){    munmap(displays[0], D1_FRAME_SIZE * NUM_BUFS);    close(fd);}/****************************************************************************** * copyFrame ******************************************************************************/static void copyFrame(char *dst, char *src, int width, int height){    int lineWidth = width * SCREEN_BPP / 8;    int xoffset   = (D1_LINE_WIDTH - lineWidth) / 2;    int ystart    = ( (D1_HEIGHT - height) / 2 ) & ~1;    int y;    /* Truncate if frame buffer higher than display buffer */    if (ystart < 0) {        ystart = 0;    }    dst += ystart * D1_LINE_WIDTH + xoffset;    /* Copy the frame into the middle of the screen */    for (y=0; y < height && y < D1_HEIGHT; y++) {        memcpy(dst, src, lineWidth);        dst += D1_LINE_WIDTH;        src += lineWidth;    }}/****************************************************************************** * displayThrFxn ******************************************************************************/void *displayThrFxn(void *arg){    DisplayEnv     *envp          = (DisplayEnv *) arg;    BufferElement   flush         = { DISPLAY_FLUSH };    void           *status        = THREAD_SUCCESS;    unsigned int    initMask      = 0;    int             displayIdx    = 0;    int             fbFd          = 0;    char           *displays[NUM_BUFS];    BufferElement   e;    /* Initialize the video display device */    fbFd = initDisplayDevice(displays);    if (fbFd == FAILURE) {        cleanup(THREAD_FAILURE);    }    DBG("Video display device initialized.\n");    initMask |= DISPLAYDEVICEINITIALIZED;    /* Signal that initialization is done and wait for other threads */    Rendezvous_meet(envp->hRendezvous);    /* Wait for the vertical sync of the display device */    waitForVsync(fbFd);    DBG("Entering display main loop.\n");    while (TRUE) {        if (!gblGetPlay() && !gblGetQuit()) {            usleep(PAUSE);            continue;        }        /* Receive a buffer with a decoded frame from the video thread */        if (FifoUtil_get(&envp->outFifo, &e) == FIFOUTIL_FAILURE) {                    breakLoop(THREAD_FAILURE);        }        /* Is the video thread flushing the pipe? */        if (e.id == DISPLAY_FLUSH) {            breakLoop(THREAD_SUCCESS);        } else if (e.id == DISPLAY_PRIME) {            pthread_mutex_lock(&envp->prime);            pthread_mutex_unlock(&envp->prime);            continue;        }        /* Increment the display index */        displayIdx = (displayIdx + 1) % NUM_BUFS;        /* Copy the supplied frame to the display frame buffer */        copyFrame(displays[displayIdx], e.frameBuffer, e.width, e.height);        /* Give back the buffer to the video thread */        if (FifoUtil_put(&envp->inFifo, &e) == FIFOUTIL_FAILURE) {            breakLoop(THREAD_FAILURE);        }        /* Flip display buffer and working buffer */        flipDisplayBuffers(fbFd, displayIdx);         /* Wait for the vertical sync of the display device */        waitForVsync(fbFd);        gblIncFrames();    }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(&envp->inFifo, &flush);    /* Clean up the display thread */    if (initMask & DISPLAYDEVICEINITIALIZED) {        cleanupDisplayDevice(fbFd, displays);    }    return status;}

⌨️ 快捷键说明

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