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

帧缓冲显示主要步骤

  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

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

时间: 2024-11-08 23:04:01

V4L2捕捉画面+H264压缩视频+帧缓冲显示视频————帧缓冲显示视频的相关文章

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

H264视频压缩主要步骤 压缩前的一些初始化 压缩帧再写入文件 压缩完成后资源的一些清理 /* encode.c */ #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <pthread.h> #include <x264.h> #include <pthread.h> #include "

(转)[视频压制/转换技术] I帧 B帧 P帧 IDR帧 等帧用途详细说明

转:http://www.u2game.net/bbs/thread-46116-1-1.html 在视频压制.转换中,经常会看到:I帧 B帧 P帧 IDR帧 等名词,这里就是通用的解释一下这些帧的用途,希望这些说明能让需要的朋友了解到一些知识...I帧 / 帧内编码帧I帧特点:1.它是一个全帧压缩编码帧.它将全帧图像信息进行JPEG压缩编码及传输:2.解码时仅用I帧的数据就可重构完整图像:3.I帧描述了图像背景和运动主体的详情:4.I帧不需要参考其他画面而生成:5.I帧是P帧和B帧的参考帧(其

安防摄像头监控视频流媒体开发中H264编码NALU结构介绍与I帧判断方法

H264编码技术介绍 H.264是ITU-T以H.26x系列为名称命名的视频编解码技术标准之一.H.264是ITU-T的VCEG(视频编码专家组)和ISO/IEC的MPEG(活动图像编码专家组)的联合视频组(JVT:joint video team)开发的一个数字视频编码标准.该标准最早来自于ITU-T的称之为H.26L的项目的开发.H.26L这个名称虽然不太常见,但是一直被使用着.H.264是ITU-T以H.26x系列为名称命名的标准之一,同时AVC是ISO/IEC MPEG一方的称呼. H.

创建一个程序读入和显示视频文件,并可以使用滑动条控制视频文件的播放。一个滑动条用来控制视频播放位置,以10为步长跳进。另一个滑动条用来控制停止/播放

/* 创建一个程序读入和显示视频文件,并可以使用滑动条控制视频文件的播放. 一个滑动条用来控制视频播放位置,以10为步长跳进.另一个滑动条用来控制 停止/播放 */ #include <cv.h> #include <highgui.h> int g_slider_position = 0; CvCapture* g_capture = NULL; int index = 0; bool flag = true; int g_slider_position1 = 0; void o

根据视频地址获取某一帧的图像

http://blog.fuckbugs.me/category/ios/ //CatchImage.h #import <Foundation/Foundation.h> @interface CatchImage : NSObject /* *videoURL:视频地址(本地/网络) *time      :第N帧 */ + (UIImage*) thumbnailImageForVideo:(NSURL *)videoURL atTime:(NSTimeInterval)time; @e

hi3531的h264压缩中修改波特率

typedef struct hiVENC_ATTR_H264_CBR_S { HI_U32 u32Gop; HI_U32 u32StatTime; HI_U32 u32ViFrmRate; HI_FR32 fr32TargetFrmRate; HI_U32 u32BitRate; HI_U32 u32FluctuateLevel; } VENC_ATTR_H264_CBR_S; u32BitRate 平均bitrate,以kbps 为单位. 取值范围:[2, 40960]. HI_S32 SA

智能直播审核方案:视频云智能业务截帧策略

近些年来,视频直播快速发展,国家对于直播内容监管的要求日益严格,如何在满足业务需求的情况下,选择成本最优的智能审核方案,是每个直播平台面对的难题.本文介绍如何以最优成本配置直播审核模板. 功能介绍一.审核场景审核场景包含对直播画面的涉黄.暴恐涉政.广告.不良场景四大维度进行审核. 智能监黄:识别直播中的×××内容.暴恐涉政识别:识别直播中的暴恐涉政内容.广告识别:识别直播中的广告信息.不良场景识别:识别直播中出现的黑屏.黑边.昏暗画面,画中画,抽烟,打架等不良场景图片.二.截帧频率高频截帧:对于

一款好用的视频转换gif的小软件——抠抠视频秀

在平常生活中,我们拍下来精彩的视频想要转换为gif动画,或是想要录制网页上的视频.电脑上的鼠标操作等等,大家可以使用以下这款很好用的视频转换gif的小软件——抠抠视频秀,这个软件操作简单方便现在推荐给大家. 1.首先我们运行“抠抠视频秀”软件,界面如下,上面是操作按键区,中间是透明的窗体(后面的向日葵是我的电脑壁纸),下面是信息提示. 2.然后我现预设一下,点击“更多”按键.选择“抓取视频的频率”---“15帧/秒”(这个数值越大,GIF录制的越完整):选择“生成GIF文件的帧频”----“选这

在传统以太网中,为什么要有最小帧长度和最大帧长度的限制

在传统以太网中,为什么要有最小帧长度和最大帧长度的限制? 以太网(IEEE 802.3)帧格式: 1.前导码:7字节0x55,一串1.0间隔,用于信号同步 2.帧起始定界符:1字节0xD5(10101011),表示一帧开始 3.DA(目的MAC):6字节 4.SA(源MAC):6字节 5.类型/长度:2字节,0-1500保留为长度域值,1536-65535保留为类型域值(0x0600-0xFFFF) 6.数据:46-1500字节 7.帧校验序列(FCS):4字节,使用CRC计算从目的MAC到数据