• Linux下V4L2捕捉画面+H264压缩视频+帧缓冲显示视频————帧缓冲显示视频


    帧缓冲显示主要步骤

    1. 打开设备文件, 比如/dev/fb0
    2. 获取framebuffer的一些信息, 比如分辨率
    3. 设置参数
    4. 映射framebuffer内存到用户空间
    5. 写入要显示的画面
    /* 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!
    ", pDevName);
    
    	if(ioctl(sDisplayPrivateData.DevFd, FBIOGET_FSCREENINFO, &FbFix)){
    		perror("Get Fb_fix_info error!");
    		return -1;
    	}
    	printf("Get Fb_fix_info successful!
    ");
    
    	if(ioctl(sDisplayPrivateData.DevFd, FBIOGET_VSCREENINFO, &FbVar)){
    		printf("Get Fb_var_info error!
    ");
    		return -1;
    	}
    	printf("Get Fb_var_info successful!
    ");
    	
    	printf("Screen origin param: physics resultion %dx%d, line length: %d
    ", FbVar.xres, FbVar.yres, FbFix.line_length);
    	printf("Screen origin param: virtual resultion %dx%d
    ", 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!
    ");
    		// return -1;
    	}
    	printf("Set Fb_var_info successful!
    ");
    
    	if(ioctl(sDisplayPrivateData.DevFd, FBIOGET_VSCREENINFO, &FbVar)) {
    		printf("Get Fb_var_info error!
    ");
    		return -1;
    	}
    	printf("Get Fb_var_info successful!
    ");
    	
    	printf("Screen after param: physics resultion %dx%d, line length: %d
    ", FbVar.xres, FbVar.yres, FbFix.line_length);
    	printf("Screen after param: virtual resultion %dx%d
    ", 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
    ", 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!
    ");
    
    	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
    ", 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
    ");
    	return 0;
    }
    
  • 相关阅读:
    Java中常见的几种加密算法
    关于redis中过期的key的处理
    Redis 的内存淘汰策略
    AES加密算法原理(加密过程)
    springboot中从配置文件中读取相关参数值
    springboot中切换配置(多个配置文件--生产、开发、测试)
    mysql跨库查询数据
    SpringBoot2.0 的默认连接池----Hikari
    Druid连接池中的缓存机制
    Opus编解码练习
  • 原文地址:https://www.cnblogs.com/rootming/p/10853997.html
Copyright © 2020-2023  润新知