📄 display.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 + -