c 实用化的文本终端实时显示摄像头视频
因为采用yuv格式,帧率都很低。图像会拖影。把图像尺寸尽量缩小,能大大改善。现在最麻烦的是图像上有黑色的闪影,不知是为啥?如是framebuffer引起的就无解了。终于找到问题了,是在显示前加了一条用黑色清屏造成的,删除此句图像马上干净完美了。
对比茄子软件拍的视频,肉眼可见的超越。
还有,每个摄像头的录像尺寸是固定的,不能乱设,否则不能显示图像,可以用前面写的查看v4l2摄像头软件查一下参数。
在这个基础上,再加上把数据写入文件,就具有录像功能了。但因为数据太大。不能长时间录像,意义不大。准备学一下mjpg格式再写。
此方法.可以编写视频回放慢放功能软件,可惜yuv格式拍摄的视频帧率都不高,一般都不会超过10帧/秒。
正准备采用多进程,管道,内存共享等方式来提高帧率,原理就是减少拍摄采样循环中非采样占用的时间。如显示,如yuv转换,一句话就是采样循环中尽量少塞入其他功能代码。
现在采用framebuffer 来显示视频不是通用方法,最完美是在gui图形界面中显示,但gui显示方法涉及到QT编程太复杂。
还有,在显示环节填充黑色字节,可以把视频图像移动到整个屏幕中任何地方。我在想,华为鸿蒙的开机动画是不是也是采用的这个显示方法。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h> //v4l2 头文件
#include <string.h>
#include <sys/mman.h>
#include <linux/fb.h>#define pic_width 640 //1280*720 640*360 960*540 320*240 424*240 848*480 640*480
#define pic_heigth 480#define WT 0 //如果图片是斜的,微调此值static int color1=0;
static int color2=0;
static int sp[3000*2000]; //摄像头图片最大尺寸
static struct fb_var_screeninfo var;#define HCQ 10 //v4l2 缓冲区个数int main(void)
{int fd = open("/dev/video0", O_RDWR);if (fd < 0) {perror("打开设备失败");return -1;}struct v4l2_format vfmt;vfmt.type = 1;vfmt.fmt.pix.width = pic_width;vfmt.fmt.pix.height =pic_heigth;vfmt.fmt.pix.pixelformat=v4l2_fourcc('Y','U','Y','V');int ret = ioctl(fd, VIDIOC_S_FMT, &vfmt);if (ret < 0) {perror("设置格式失败");}struct v4l2_requestbuffers reqbuffer;reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;reqbuffer.count = HCQ;reqbuffer.memory = V4L2_MEMORY_MMAP ;ret = ioctl(fd, VIDIOC_REQBUFS, &reqbuffer);if (ret < 0) {perror("申请队列空间失败");}//我理解以下部分struct v4l2_buffer mapbuffer; //相当于在为mapbuffer 设置读写规则,还没有开始数据传输,怎样���摄像头buf传输数据保存在多少个mmap中mapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;unsigned char *mptr[HCQ];for (int t = 0; t < HCQ; t++) {mapbuffer.index = t;ret = ioctl(fd, VIDIOC_QUERYBUF, &mapbuffer);//读摄像头缓冲区数据,为映射mmap准备if(ret < 0){perror("查询内核空间队列失败");}mptr[t] = mmap(NULL, mapbuffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mapbuffer.m.offset); //摄像头缓冲区映射到内存// size[t] = mapbuffer.length;ret = ioctl(fd, VIDIOC_QBUF, &mapbuffer); //释放一个buf缓冲区空间,摄像头可以为此buf写入数据if (ret < 0) {perror("放回失败");}}
//--------------------------我的理解:以上都是设置---------------------------------------------
//============================================================================================int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;ret = ioctl(fd, VIDIOC_STREAMON, &type); //启动流,数据开始传输if (ret < 0) {perror("开启失败");}struct v4l2_buffer readbuffer;readbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //安装mapbuffer设置的规矩来读,数据从mmap中提取
//---------------------------------------------------------------------------while(1){ret = ioctl(fd, VIDIOC_DQBUF, &readbuffer); //读当前队列缓冲区的数据 index循环+1,VIDIOC_DQBUF执行一次,index加1if (ret < 0) {perror("提取数据失败");}int i=readbuffer.index;int len = readbuffer.length;char (*p)[4]=(char (*)[4])mptr[i]; // p[][0]=Y p[][1]=U p[][2]=Y p[][3]=V//R = Y + 1.4075 *(V-128)//G = Y – 0.3455 *(U –128) – 0.7169 *(V –128)// B = Y + 1.779 *(U – 128)int t=0;int u=0;while(1){if(4*t>=len){break;}int Y1=(unsigned char)p[t][0];if((4*t+1)>=len){break;}int U=(unsigned char)p[t][1];if((4*t+2)>=len){break;}int Y2=(unsigned char)p[t][2];if((4*t+3)>=len){break;}int V=(unsigned char)p[t][3];//-------------------------------------------------int B0=Y1+1.779*(U-128);if(B0>255) B0=255;if(B0<0) B0=0;int G0=Y1-0.3455*(U-128)-0.7169*(V-128);if(G0>255) G0=255;if(G0<0) G0=0;int R0=Y1+1.4075*(V-128);if(R0>255) R0=255;if(R0<0) R0=0;int B1=Y2+1.779*(U-128);if(B1>255) B1=255;if(B1<0) B1=0;int G1=Y2-0.3455*(U-128)-0.7169*(V-128);if(G1>255) G1=255;if(G1<0) G1=0;int R1=Y2+1.4075*(V-128);if(R1>255) R1=255;if(R1<0) R1=0;color1=(R0<<16)|(G0<<8)|B0;color2=(R1<<16)|(G1<<8)|B1;sp[u]=color1;sp[u+1]=color2;t++;u=u+2;}//--------------------------------int fd_fb = open("/dev/fb0", O_RDWR);if (fd_fb < 0){puts("/dev/fb0 error");return -1;}if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var)){puts("ioctl error");return -1;}// unsigned int pixel_width = var.bits_per_pixel / 8; //deepin=32int screen_size = var.xres * var.yres * var.bits_per_pixel / 8; //刚好等于图片的长乘宽unsigned char *fb_base = mmap(NULL, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);if (fb_base == NULL){puts("mmap error");return -1;}
// memset(fb_base,0, screen_size); //设底色为黑色 必须删除这句,否则要造成黑带屏闪int zz=0;var.xres=var.xres+WT; //如果图片是斜的,微调WT的值for(int a=0;a<var.yres;a++){for(int b=0;b<var.xres;b++){unsigned int (*p)[var.xres]=(unsigned int (*)[var.xres])fb_base; //此处不能用图片的尺寸,因为有不同尺���大小if(b<pic_width){ //如果图片宽度小于framebuffer 的宽度,小与部分填充0(黑色)p[a][b]=sp[zz]; //sp[zz]zz++;}else{p[a][b]=0; //填充黑色}}}ret = ioctl(fd, VIDIOC_QBUF, &readbuffer); //把缓冲区数据放入读队列中if (ret < 0) {perror("放回失败");}munmap(fb_base, screen_size);close(fd_fb);}puts("over");return 0;
}
相关文章:
c 实用化的文本终端实时显示摄像头视频
因为采用yuv格式,帧率都很低。图像会拖影。把图像尺寸尽量缩小,能大大改善。现在最麻烦的是图像上有黑色的闪影,不知是为啥?如是framebuffer引起的就无解了。终于找到问题了,是在显示前加了一条用黑色清屏造成的&#…...
CSS中常用的伪类选择器
一 、伪类(不存在的类,特殊的类) -伪类用来描述一个元素的特殊状态 比如:第一个元素,被点击的元素,鼠标移入的元素 -特点:一般请情况下,使用:开头 1、 :first-child …...
【python学习】中级篇-数据库操作:SQLite
SQLite是一个轻量级的数据库引擎,它可以嵌入到各种应用程序中。以下是SQLite的基本用法: 创建数据库文件 import sqlite3# 连接到一个不存在的数据库文件,如果文件不存在,将会自动创建一个新的数据库文件 conn sqlite3.connect…...
汇编-PROTO声明过程
64位汇编 64 模式中,PROTO 伪指令指定程序的外部过程,示例如下: ExitProcess PROTO ;指定外部过程,不需要参数.code main PROCmov ebx, 0FFFFFFFFh mov ecx,0 ;结束程序call ExitProcess ;调用外部过程main ENDP END 32位…...
MYSQL事务操作
...
自动化测试——自动卸载软件
📢专注于分享软件测试干货内容,欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!📢交流讨论:欢迎加入我们一起学习!📢资源分享:耗时200小时精选的「软件测试」资…...
Linux - 系统调用(syscall)
说明 基于riscv64 soc linux_5.10.4平台,通过新增一个系统调用深入了解下系统调用实现原理。 简介 Linux 软件运行环境分为用户空间和内核空间,默认情况下,用户进程无法访问内核,既不能访问内核所在的内存空间,也不…...
c语言-冒泡排序
冒泡排序原理: 冒泡排序是一种简单直观的排序算法,它重复地遍历待排序的元素序列,比较相邻的两个元素,如果它们的顺序不符合要求(例如升序要求前面的元素小于后面的元素),则交换它们的位置。遍历…...
Mysql面经
Select语句的执行顺序 1、from 子句组装来自不同数据源的数据; 2、where 子句基于指定的条件对记录行进行筛选; 3、group by 子句将数据划分为多个分组; 4、使用聚集函数进行计算;AVG() SUM() MAX() MIN() COUNT() 5、使用 havin…...
1panel可视化Docker面板安装与使用
官网地址1Panel - 现代化、开源的 Linux 服务器运维管理面板 文章目录 目录 文章目录 前言 一、环境准备 二、使用步骤 1.安装命令 2.一些命令 3.使用 总结 前言 一、环境准备 虚拟机centos 已经安装好docker和 Docker Compose 或者都没安装 1panel会帮你自动安装 二、使用…...
es6中的import导入模块 和 export导出模块
es6中的import导入模块 和 export导出模块 一、定义二、使用1.默认导出导入2..命名导出导入3.命名导出(Named Export)与默认导出(Default Export)结合使用 三、总结 一、定义 功能:用于导入和导出模块的内容。 静态加载…...
WordPress插件开发教程手册 — 钩子(Hooks)
钩子是用一段代码添加/修改另外一段代码的方式,是 WordPress插件和主题与 WordPress 内核交互的基础,钩子在 WordPress 内核中也被广泛使用。WordPress 中有两种钩子,Action 和 Filter。使用钩子时,我们需要先编写一个自定义函数作…...
Python开发运维:Celery连接Redis
目录 一、理论 1.Celery 二、实验 1.Windows11安装Redis 2.Python3.8环境中配置Celery 3.celery的多目录结构异步执行 4.celery简单结构下的定时任务 三、问题 1.Celery命令报错 2.执行Celery命令报错 3.Win11启动Celery报ValueErro错误 4.Pycharm 无法 import 同目…...
JSP:JDBC
JDBC(Java Data Base Connectivity的缩写)是Java程序操作数据库的API,也是Java程序与数据库相交互的一门技术。 JDBC是Java操作数据库的规范,由一组用Java语言编写的类和接口组成,它对数据库的操作提供基本方法&#…...
能否在一台电脑上安全地登录多个Facebook账号?
Facebook是一个流量大、用户多的平台,许多人可能需要在一台设备上管理多个Facebook账号,无论是出于个人或职业需求,都能带来极大地便利。然而,保持每个账号的安全性和隐私性却是一个挑战。本文将介绍如何在一台电脑上安全地登录多…...
Banana Pi [BPi-R3-Mini] 回顾和主线 ImmortalWrt 固件支持
BananaPi BPi-R3 Mini 采用 MediaTek 830(4 个 A53,最高 2.0 GHz),具有 2 个 2.5 GbE、AX4200 2.4G/5G 无线和 USB 2.0 端口。它还具有两个 M.2 连接器,可用于 NVMe SSD 和 5G 模块(板上包含 Nano SIM 插槽…...
2001-2022年上市公-供应链话语权测算数据(原始数据+处理代码Stata do文档+结果)
2001-2022年上市公-供应链话语权测算数据(原始数据处理代码Stata do文档结果) 1、时间:2001-2022年 2、指标:企业代码、股票代码、年份、股票简称、上市公司前五大供应商的采购额之和占企业当年总采购额的比例、上市公司前五大客…...
如何通过ShardingJDBC进行读写分离
背景信息: 面对日益增加的系统访问量,数据库的吞吐量面临着巨大瓶颈。 对于同一时刻有大量并发读操作和较少写操作类型的应用系统来说,将数据库拆分为主库和从库。其中主库负责处理事务性的增删改操作,从库负责处理查询操作&#…...
【uniapp】部分图标点击事件无反应
比如:点击这个图标在h5都正常,在小程序上无反应 css:也设置z-index,padding 页面上也试过click.native.stop.prevent"changePassword()" 时而可以时而不行, 最后发现是手机里输入键盘的原因,输…...
前端vue导出PPT,使用pptxgen.js
前言 公司新需求需要导出ppt给业务用,查阅资料后发现也挺简单的,记录一下。 如有不懂的可以留言!!! 1.安装包 npm install pptxgenjs --save2.引入包 在需要使用的文件中引入 import Pptxgenfrom "pptxgenjs&…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...
【iOS】 Block再学习
iOS Block再学习 文章目录 iOS Block再学习前言Block的三种类型__ NSGlobalBlock____ NSMallocBlock____ NSStackBlock__小结 Block底层分析Block的结构捕获自由变量捕获全局(静态)变量捕获静态变量__block修饰符forwarding指针 Block的copy时机block作为函数返回值将block赋给…...
