Linux下V4L2捕捉畫面+H264壓縮視頻+幀緩沖顯示視頻————幀緩沖顯示視頻
阿新 • • 發佈:2019-05-13
man type fix unmap success pthread tin ack err
幀緩沖顯示主要步驟
- 打開設備文件, 比如/dev/fb0
- 獲取framebuffer的一些信息, 比如分辨率
- 設置參數
- 映射framebuffer內存到用戶空間
- 寫入要顯示的畫面
/* display.h */
#ifndef DISPLAY_H
#define DISPLAY_H
int DisplayInit(const char* pDevName);
int DisplayStart(void);
int DisplayStop(void);
#endif
/* display.c */ #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/stat.h> #include <sys/time.h> #include <linux/fb.h> #include <pthread.h> #include "config.h" #include "queue.h" #include "display.h" typedef enum { DISPLAY_STATE_STOP, DISPLAY_STATE_START } eDisplayState; static struct { int DevFd; int ScreenSize; uint8_t* pMmap; eDisplayState State; pthread_t DisplayThreadId; sQueue QueuePrivateData; uint32_t ScreenWidth; uint32_t ScreenHeight; } sDisplayPrivateData; static const int BufferSize = CONFIG_CAPTURE_WIDTH * CONFIG_CAPTURE_HEIGHT * 4; extern int Yuyv2Rgb32(uint8_t* pYuv, uint8_t* pRgb, uint32_t Width, uint32_t Height); int DisplayInit(const char* pDevName) { QueueInit(&sDisplayPrivateData.QueuePrivateData); struct fb_fix_screeninfo FbFix; struct fb_var_screeninfo FbVar; if((sDisplayPrivateData.DevFd = open(pDevName, O_RDWR)) < 0){ perror("Open Framebuffer Device"); return -1; } printf("Open Framebuffer Device:%s successful!\n", pDevName); if(ioctl(sDisplayPrivateData.DevFd, FBIOGET_FSCREENINFO, &FbFix)){ perror("Get Fb_fix_info error!"); return -1; } printf("Get Fb_fix_info successful!\n"); if(ioctl(sDisplayPrivateData.DevFd, FBIOGET_VSCREENINFO, &FbVar)){ printf("Get Fb_var_info error!\n"); return -1; } printf("Get Fb_var_info successful!\n"); printf("Screen origin param: physics resultion %dx%d, line length: %d\n", FbVar.xres, FbVar.yres, FbFix.line_length); printf("Screen origin param: virtual resultion %dx%d\n", FbVar.xres_virtual, FbVar.yres_virtual); // FbVar.xres = CONFIG_CAPTURE_WIDTH; // FbVar.yres = CONFIG_CAPTURE_HEIGHT; FbVar.xres_virtual = CONFIG_CAPTURE_WIDTH; FbVar.yres_virtual = CONFIG_CAPTURE_WIDTH; if(ioctl(sDisplayPrivateData.DevFd, FBIOPUT_VSCREENINFO, &FbVar)) { printf("Set Fb_var_info error!\n"); // return -1; } printf("Set Fb_var_info successful!\n"); if(ioctl(sDisplayPrivateData.DevFd, FBIOGET_VSCREENINFO, &FbVar)) { printf("Get Fb_var_info error!\n"); return -1; } printf("Get Fb_var_info successful!\n"); printf("Screen after param: physics resultion %dx%d, line length: %d\n", FbVar.xres, FbVar.yres, FbFix.line_length); printf("Screen after param: virtual resultion %dx%d\n", FbVar.xres_virtual, FbVar.yres_virtual); sDisplayPrivateData.ScreenWidth = FbVar.xres; sDisplayPrivateData.ScreenHeight = FbVar.yres; sDisplayPrivateData.ScreenSize = FbVar.xres * FbVar.yres * (FbVar.bits_per_pixel / 8); printf("Screen size: %d\n", sDisplayPrivateData.ScreenSize); sDisplayPrivateData.pMmap = mmap(NULL, sDisplayPrivateData.ScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, sDisplayPrivateData.DevFd, 0); if(!sDisplayPrivateData.pMmap){ perror("Memory Mmap error"); return -1; } printf("Memory Mmap successful!\n"); return 0; } static void* DisplayThread(void* pParam) { int Ret = -1; sDisplayPrivateData.State = DISPLAY_STATE_START; uint8_t* pRgbBuffer = malloc(BufferSize); if(!pRgbBuffer) { perror("Malloc failed"); return NULL; } while(sDisplayPrivateData.State == DISPLAY_STATE_START) { sQueueData QueueData; Ret = QueuePopData(&sDisplayPrivateData.QueuePrivateData, &QueueData); if(Ret) { continue; } Yuyv2Rgb32(QueueData.pData, pRgbBuffer, CONFIG_CAPTURE_WIDTH, CONFIG_CAPTURE_HEIGHT); // printf("Copy length: %d\n", BufferSize); // memcpy(sDisplayPrivateData.pMmap, pRgbBuffer, BufferSize); uint32_t CopyWidthLength = sDisplayPrivateData.ScreenWidth > CONFIG_CAPTURE_WIDTH ? CONFIG_CAPTURE_WIDTH : sDisplayPrivateData.ScreenWidth; for(int i = 0; i < CONFIG_CAPTURE_HEIGHT; i++) { memcpy(sDisplayPrivateData.pMmap + sDisplayPrivateData.ScreenWidth * 4 * i, &pRgbBuffer[CONFIG_CAPTURE_WIDTH * 4 * i], CopyWidthLength * 4); } QueueCallback(&QueueData); } free(pRgbBuffer); DisplayStop(); return NULL; } int DisplayStart(void) { if(sDisplayPrivateData.State == DISPLAY_STATE_START) { return -1; } pthread_create(&sDisplayPrivateData.DisplayThreadId, NULL, DisplayThread, (void *)NULL); return 0; } int DisplayStop(void) { if(sDisplayPrivateData.State == DISPLAY_STATE_STOP) { return 0; } sDisplayPrivateData.State = DISPLAY_STATE_STOP; pthread_join(sDisplayPrivateData.DisplayThreadId, NULL); munmap(sDisplayPrivateData.pMmap, sDisplayPrivateData.ScreenSize); close(sDisplayPrivateData.DevFd); printf("Display thread stop\n"); return 0; }
Linux下V4L2捕捉畫面+H264壓縮視頻+幀緩沖顯示視頻————幀緩沖顯示視頻