码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-05-12 22:31:25      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:success   splay   i++   device   oid   pixel   munmap   文件   efi   

帧缓冲显示主要步骤

  1. 打开设备文件, 比如/dev/fb0
  2. 获取framebuffer的一些信息, 比如分辨率
  3. 设置参数
  4. 映射framebuffer内存到用户空间
  5. 写入要显示的画面
/* 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;
}
/* display.h */
#ifndef DISPLAY_H
#define DISPLAY_H


int DisplayInit(const char* pDevName);
int DisplayStart(void);
int DisplayStop(void);

#endif

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

标签:success   splay   i++   device   oid   pixel   munmap   文件   efi   

原文地址:https://www.cnblogs.com/rootming/p/10853997.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!