linux下通过V4L2驱动USB摄像头

2023-10-29

目录

文章目录

 

前言

在移植罗技C270摄像头到6818的过程中,内核已经检测到了USB摄像头,但是直接用OpenCV的API(比如CvCapture*cvCaptureFromCAM(int index)接口,无法打开USB摄像头,至少目前我是这么认为的。然后,网上搜索答案说是要使用V4l2进行操作。没有别的办法!只有一边学一边试试看行不行喽!

感谢超群天晴大神的(原创)基于ZedBoard的Webcam设计(一):USB摄像头(V4L2接口)的图片采集这篇博文中提供的源码,我直接移植后,在6818是成功获取bmp图片和yuv图片。虽然在Ubuntu中打开bmp图片和yuv图片是错误的!!!

在找到超群天晴的博文后,我又找到这两篇博客和菜鸟一起学linux之V4L2摄像头应用流程嵌入式LINUX环境下视频采集知识验证成功后,就是花时间理解,然后获取视频流了!希望获取的视频流能够流畅!

学习!分享!感谢!

v4l2解析

v4l2介绍

v4l2是linux操作系统下用于采集图片、视频和音频数据的API接口,配合适当的视频采集设备和相应的驱动程序,可以实现图片、视频、音频等的采集。在远程会议、可视电话、视频监控系统和嵌入式多媒体终端中都有广泛应用。
在linux下,所有外设都被看成一种特殊的文件,称为"设备文件",可以像访问普通文件一样对设备文件进行访问。
V4L2支持两种方式来采集图像:内存映射(mmap)和直接读取方式(read)。V4L2在include/linux/video.h文件下定义了一些重要的数据结构,在采集图像的过程中,就是通过对这些数据的操作来获得最终的图像数据。Linux系统V4L2使能可在内核编译阶段配置,默认情况下是在make menuconfig是打开的。

linux下视频捕捉具体的linux调用参见下图:
1

应用程序可以通过V4L2进行视频采集。V4L2支持内存映射(mmap)方式和直接读取方式(read)方式采集数据。前者一般用于连续的视频数据采集,后者常用静态图片数据采集。

v4l2 中不仅定义了通用API元素,图像的格式,输入/输出方法,还定义了Linux内核驱动处理视频信息的一系列接口,这些接口主要有:

视频采集接口——Video Capture interface 视频输出接口 ——Video Output Interface; 视频覆盖/预览接口——Video Overlay Interface; 视频输出覆盖接口—— Video Output Overlay Interface; 编解码接口——Codec Interface

应用程序通过V4L2接口采集视频数据步骤

  • 打开视频设备文件,通过视频采集的参数初始化,通过V4L2接口设置视频图像属性。

  • 申请若干视频采集的帧缓存区,并将这些帧缓冲区从内核空间映射到用户空间,便于应用程序读取/处理视频数据。

  • 将申请到的帧缓冲区在视频采集输入队列排队,并启动视频采集。

  • 驱动开始视频数据的采集,应用程序从视频采集输出队列中取出帧缓冲区,处理后,将帧缓冲区重新放入视频采集输入队列,循环往复采集连续的视频数据。

  • 停止视频采集。
    具体实现过程如下图:
    2

  • 整理下其中ioctl控制符:

VIDIOC_QUERYCAP	查询设备的属性
VIDIOC_ENUM_FMT 帧格式
VIDIOC_S_FMT 设置视频帧格式,对应struct v4l2_format
VIDIOC_G_FMT 获取视频帧格式等
VIDIOC_REQBUFS 请求/申请若干个帧缓冲区,一般为不少于3个
VIDIOC_QUERYBUF 查询帧缓冲区在内核空间的长度和偏移量
VIDIOC_QBUF 将申请到的帧缓冲区全部放入视频采集输出队列
VIDIOC_STREAMON 开始视频流数据的采集
VIDIOC_DQBUF 应用程序从视频采集输出队列中取出已含有采集数据的帧缓冲区
VIDIOC_STREAMOFF 应用程序将该帧缓冲区重新挂入输入队列

其实,图解过程已经很详细了,但是比较笨,而且图片也比较容易眼花,重新总结下。整个过程:
首先:先启动视频采集,驱动程序开始采集一帧数据,把采集的数据放入视频采集输入队列的第一个帧缓冲区,一帧数据采集完成,也就是第一个帧缓冲区存满一帧数据后,驱动程序将该帧缓冲区移至视频采集输出队列,等待应用程序从输出队列取出。驱动程序则继续采集下一帧数据放入第二个缓冲区,同样帧缓冲区存满下一帧数据后,被放入视频采集输出队列。
然后:应用程序从视频采集输出队列中取出含有视频数据的帧缓冲区,处理帧缓冲区中的视频数据,如存储或压缩。
最后:应用程序将处理完数据的帧缓冲区重新放入视频采集输入队列,这样可以循环采集。
看到这里,摘录一段Hi3519的开发文档中《系统控制》部分的介绍:

视频缓存池主要向媒体业务提供大块物理内存管理功能,负责内存的分配和回收,充分发挥内存缓存池的作用,让物理内存资源在各个媒体处理模块中合理使用。
一组大小相同、物理地址连续的缓存块组成一个视频缓存池。
视频输入通道需要使用公共视频缓存池。所有的视频输入通道都可以从公共视频缓存池中获取视频缓存块用于保存采集的图像。由于视频输入通道不提供创建爱你和销毁公共视频缓存池功能。因此,在系统初始化之前,必须为视频输入通道配置公共缓存池。根据业务的不同,公共缓存池的数量、缓存块的大小和数量不同。缓存块的生存期是指经过VPSS通道传给后续模块的情形。如果该缓存块完全没有经过VPSS通道传给其他模块,则将在VPSS模块处理后被放回公共缓存池。
3
所以,我们从摄像头中获取的视频帧数据会放入视频缓存队列中,当其他模块需要处理对应的视频帧的时候,就会占用缓存块,也就是这一块内存被占用,当处理完之后,对应的数据通过VO/VENC/VDA显示之后,这一缓存块就没有用了,可以回收利用。现在来看,其实海思的底层处理和linux的底层处理是一样的。不过海思本身使用的就是linux内核。应该也就是对这一块进行封装了而已吧!
4
从这张图可以看出,海思的公共视频缓存池按我的理解应该有两部分,一部分是视频采集输入队列,另一部分是视频采集输出队列,VI通道是是视频采集输出队列中获取的视频帧,而中间linux内核的驱动程序会在视频采集输入队列中填充视频帧,变成视频输出队列。
每一个帧缓冲区都有一个对应的状态标志变量,其中每一个比特代表一个状态:

V4L2_BUF_FLAG_UNMAPPED 	0B0000
V4L2_BUF_FLAG_MAPPED 	0B0001
V4L2_BUF_FLAG_ENQUEUED 	0B0010
V4L2_BUF_FLAG_DONE 		0B0100

缓冲区的状态转化如图:
5
在申请了缓冲区(VIDIOC_REQBUFS)后标志为0000,但是这时候还没有映射到应用层,所以在Mmap之后,缓冲区的表示为0001。
应用程序(VIDIOC_DQBUF)从视频采集输出队列中取出已含有采集数据的帧缓冲区,这时候(V4L2_BUF_FLAG_DONE|V4L2_BUF_FLAG_MAPPED),所以缓冲区标志为0101.
VIDIOC_QBUF将申请到的帧缓冲区全部放入视频采集输出队列:V4L2_BUF_FLAG_ENQUEUED|V4L2_BUF_FLAG_MAPPED

相关结构体解析

  1. VIDIOC_QUERYCAP-------->struct v4l2_capability
struct v4l2_capability {
	__u8	driver[16];    // 驱动模块的名字
	__u8	card[32];      // 设备名字
	__u8	bus_info[32];  // 总线信息
	__u32   version;       // 内核版本
	__u32	capabilities;  // 整个物理设备支持的功能
	__u32	device_caps;   // 通过这个特定设备访问的功能
	__u32	reserved[3];
};

如下是我的罗技C270摄像头的通过VIDIOC_QUERYCAP获取的设备功能

driver:         uvcvideo
card:           UVC Camera (046d:0825)
bus_info:       usb-nxp-ehci-1.3
version:        197671
capabilities:   4000001
Device /dev/video9: supports capture.
Device /dev/video9: supports streaming.

其中capabilities: 4000001通过与各种宏位与,可以获得物理设备的功能属性。比如:

        //#define V4L2_CAP_VIDEO_CAPTURE		0x00000001  /* Is a video capture device */ // 是否支持视频捕获
     	if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == V4L2_CAP_VIDEO_CAPTURE) 
     	{
            printf("Device %s: supports capture.\n", FILE_VIDEO);
		}

        //#define V4L2_CAP_STREAMING            0x04000000  /* streaming I/O ioctls */ // 是否支持输入输出流控制
		if ((cap.capabilities & V4L2_CAP_STREAMING) == V4L2_CAP_STREAMING) 
		{
            printf("Device %s: supports streaming.\n", FILE_VIDEO);
		}
  1. VIDIOC_ENUM_FMT-------->struct v4l2_fmtdesc
/*
 *	F O R M A T   E N U M E R A T I O N
 */
struct v4l2_fmtdesc {
	__u32		    index;           /* Format number      */
	__u32		    type;            /* enum v4l2_buf_type */
	__u32           flags;
	__u8		    description[32]; /* Description string */
	__u32		    pixelformat;     /* Format fourcc      */
	__u32		    reserved[4];
};

通过这个结构体,可以显示对应的摄像头所支持视频帧格式。

struct v4l2_fmtdesc fmtdesc;  
fmtdesc.index = 0;  
fmtdesc.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
printf("Supportformat:/n");  
while(ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) != -1)  
{  
printf("/t%d.%s/n",fmtdesc.index+1,fmtdesc.description);  
fmtdesc.index++;  
}  

我的摄像头输出如下:

Support format:
        1.YUV 4:2:2 (YUYV)
        2.MJPEG

所以,我要读取视频帧的时候就要使用YUV422这种格式。
3. VIDIOC_S_FMT&VIDIOC_G_FMT-------->struct v4l2_format
查看或设置视频帧格式

struct v4l2_format {
	__u32	 type; // 帧类型
	union {
		/* V4L2_BUF_TYPE_VIDEO_CAPTURE */
		struct v4l2_pix_format pix;  //像素格式
		/* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
		struct v4l2_pix_format_mplane pix_mp; 
		/* V4L2_BUF_TYPE_VIDEO_OVERLAY */
		struct v4l2_window win; 
		/* V4L2_BUF_TYPE_VBI_CAPTURE */
		struct v4l2_vbi_format vbi; 
		/* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
		struct v4l2_sliced_vbi_format sliced; 
		/* V4L2_BUF_TYPE_SDR_CAPTURE */
		struct v4l2_sdr_format		sdr; 
		/* user-defined */    
		__u8	raw_data[200];                  
	} fmt;
};
/*
 *	V I D E O   I M A G E   F O R M A T
 */
struct v4l2_pix_format {
	__u32           width;  // 像素高度
	__u32			height; // 像素宽度
	__u32			pixelformat; // 像素格式
	__u32			field;		/* enum v4l2_field */
	__u32           bytesperline; /* for padding, zero if unused */
	__u32          		sizeimage;
	__u32			colorspace;	/* enum v4l2_colorspace */
	__u32			priv;		/* private data, depends on pixelformat */
	__u32			flags;		/* format flags (V4L2_PIX_FMT_FLAG_*) */
	__u32			ycbcr_enc;	/* enum v4l2_ycbcr_encoding */
	__u32			quantization;	/* enum v4l2_quantization */
	__u32			xfer_func;	/* enum v4l2_xfer_func */
};

仔细看,发现这些其实和海思中的一些结构体非常类似,linux真的很强大!
4. VIDIOC_CROPCAP-------->struct v4l2_cropcap
5. VIDIOC_G_PARM&VIDIOC_S_PARM-------->struct v4l2_streamparm
设置Stream信息,主要设置帧率

struct v4l2_streamparm {
	__u32	 type;			/* enum v4l2_buf_type */
	union {
		struct v4l2_captureparm	capture;
		struct v4l2_outputparm	output;
		__u8	raw_data[200];  /* user-defined */
	} parm;
};
struct v4l2_captureparm {
	/*  Supported modes */
	__u32		   capability;	
	/*  Current mode */  
	__u32		   capturemode;	  
	/*  Time per frame in seconds */
	struct v4l2_fract  timeperframe;  
	/*  Driver-specific extensions */
	__u32		   extendedmode;  
	/*  # of buffers for read */
	__u32          readbuffers;   
	__u32		   reserved[4];
};
// timeperframe
// numerator和denominator可描述为每numerator秒有denominator帧
struct v4l2_fract {
	__u32   numerator;         // 分子
	__u32   denominator;       // 分母 
};
  1. VIDIOC_REQBUFS-------->struct v4l2_requestbuffers
    申请和管理缓冲区,应用程序和设备有三种交换数据方法,直接read/write(裸机)、内存映射(系统),用户指针(…)。一般在操作系统管理下,都是使用内存映射的方式。
/*
 *	M E M O R Y - M A P P I N G   B U F F E R S
 */
struct v4l2_requestbuffers {
	__u32			count;  // 缓冲区内缓冲帧的数目
	__u32			type;   // 缓冲帧数据格式
	__u32			memory; // 
	__u32			reserved[2];
};

enum v4l2_memory {
	V4L2_MEMORY_MMAP             = 1, // 内存映射
	V4L2_MEMORY_USERPTR          = 2, // 用户指针
	V4L2_MEMORY_OVERLAY          = 3,
	V4L2_MEMORY_DMABUF           = 4,
};
  1. VIDIOC_QUERYBUF-------->struct v4l2_buffer
struct v4l2_buffer {
	__u32			index;           // buffer的id
	__u32			type;            // enum v4l2_buf_type
	__u32			bytesused;       // buf中已经使用的字节数
	__u32			flags;           // MMAP 或 USERPTR
	__u32			field;
	struct timeval		timestamp;   // 帧时间戳
	struct v4l2_timecode	timecode;
	__u32			sequence;        // 队列中的序号

	/* memory location */
	__u32			memory;
	union {
		__u32           offset;      // 设备内存起始offset
		unsigned long   userptr;     // 指向用户空间的指针
		struct v4l2_plane *planes;
		__s32		fd;
	} m;
	__u32			length;         // 缓存帧长度
	__u32			reserved2;
	__u32			reserved;
};
  1. VIDIOC_DQBUF
    应用程序从视频采集输出队列中取出已含有采集数据的帧缓冲区

  2. VIDIOC_STREAMON&VIDIOC_STREAMOFF
    开始视频采集和关闭视频采集

  3. VIDIOC_QBUF
    应用程序将该帧缓冲区重新挂入输入队列

总结

使用C语言高级应用—操作linux下V4L2摄像头应用程序源码成功的在我的开发板上显示出了800600的视频图像。我的开发板的显示屏是1024600的,当我设置为1024600时,实际显示为1024576,感觉很奇怪!而且显示的视频是反的,都是小问题。总之,显示视频的那一刻真的好开心!

参考链接

和菜鸟一起学linux之V4L2摄像头应用流程
(原创)基于ZedBoard的Webcam设计(一):USB摄像头(V4L2接口)的图片采集
V4L2 API详解 <二> Camera详细设置
V4L2 API
V4L2采集yuv视频花屏:Linux视频采集与编码(一)
C语言高级应用—操作linux下V4L2摄像头应用程序
v4l2 编程接口(一) — ioctl
capture.c
支持的uvc设备查询

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux下通过V4L2驱动USB摄像头 的相关文章

  • 码头无故停止

    我需要经验丰富的码头用户的建议 我在负载均衡器 亚马逊云 后面维护着 2 台 Linux 机器 使用 Jetty 9 0 3 有时我的 Jetty 容器会被 Thread 2 无故关闭 同时地 显示以下日志并且容器无故停止 没有错误 没有例
  • 找出 Linux 上的默认语言

    有没有办法从C语言中找出Linux系统的默认语言 有 POSIX API 可以实现这个功能吗 例如 我想要一个人类可读格式的字符串 即德语系统上的 German 或 Deutsch 法语系统上的 French 或 Francais 等 有类
  • 未找到 Gem 命令

    我已经在 Ubuntu 10 10 32 位上安装了 gem apt get install gem y 但当我尝试跑步时 gem install something gem 我收到未找到命令的错误 bash gem command not
  • 使用 gcc 理解共享库

    我试图理解 C 中共享库的以下行为 机器一 cat one c include
  • 在 Docker 容器中以主机用户身份运行

    在我的团队中 我们在进行开发时使用 Docker 容器在本地运行我们的网站应用程序 假设我正在开发 Flask 应用程序app py具有依赖关系requirements txt 工作流程大致如下 I am robin and I am in
  • 用于读取文件的 Bash 脚本

    不知道为什么最后一行没有从脚本中删除 bin bash FILENAME 1 while read line do cut d f2 echo line done lt FILENAME cat file 1 test 2 test 3 t
  • 使用 ProcessBuilder 运行 shell 脚本

    我正在尝试使用 Java 和 ProcessBuilder 运行脚本 当我尝试运行时 我收到以下消息 error 2 没有这样的文件或目录 我不知道我做错了什么 但这是我的代码 ps 我尝试只执行不带参数的脚本 错误是相同的 String
  • 使用c在linux上分块读写

    我有一个 ASCII 文件 其中每一行都包含一个可变长度的记录 例如 Record 1 15 characters Record 2 200 characters Record 3 500 characters Record n X cha
  • 如何反汇编、修改然后重新组装 Linux 可执行文件?

    无论如何 这可以做到吗 我使用过 objdump 但它不会产生我所知道的任何汇编器都可以接受的汇编输出 我希望能够更改可执行文件中的指令 然后对其进行测试 我认为没有任何可靠的方法可以做到这一点 机器代码格式非常复杂 比汇编文件还要复杂 实
  • 为什么docker容器提示“权限被拒绝”?

    我使用以下命令来运行 docker 容器 并从主机映射目录 root database 到容器 tmp install database docker run it name oracle install v root database t
  • 可以作为命令行参数传递多少数据?

    在 Linux 下生成进程时可以发送多少字节作为命令行参数 gahooa 推荐了一篇好文章http www in ulm de mascheck various argmax http www in ulm de mascheck vari
  • 如何在文件夹中的 xml 文件中 grep 一个单词

    我知道我可以使用 grep 在这样的文件夹中的所有文件中查找单词 grep rn core 但我当前的目录有很多子目录 我只想搜索当前目录及其所有子目录中存在的所有 xml 文件 我怎样才能做到这一点 我试过这个 grep rn core
  • Bash - 比较 2 个文件列表及其 md5 校验和

    我有 2 个列表 其中包含带有 md5sum 检查的文件 即使文件相同 列表也具有不同的路径 我想检查每个文件的 md5 和 我们正在讨论数千个文件 这就是为什么我需要脚本来仅显示差异 第一个列表是普通列表 第二个列表是文件的当前状态 我想
  • 用于获取特定用户 ID 和进程数的 Bash 脚本

    我需要 bash 脚本来计算特定用户或所有用户的进程 我们可以输入 0 1 或更多参数 例如 myScript sh root deamon 应该像这样执行 root 92 deamon 8 2 users has total proces
  • 为什么 call_usermodehelper 大多数时候都会失败?

    从内核模块中 我尝试使用 call usermodehelper 函数来执行可执行文件 sha1 该可执行文件将文件作为参数并将文件的 SHA1 哈希和写入另一个文件 名为输出 可执行文件完美运行 int result 1 name hom
  • 在用户程序中使用 或在驱动程序模块代码中使用 ...这有关系吗?

    我正在开发一个设备驱动程序模块和关联的用户库来处理ioctl 来电 该库获取相关信息并将其放入一个结构中 该结构被传递到驱动程序模块中并在那里解压 然后进行处理 我省略了很多步骤 但这就是总体思路 一些数据通过结构体传递ioctl is u
  • 亚马逊 Linux - 安装 openjdk-debuginfo?

    我试图使用jstack在 ec2 实例上amazon linux 所以我安装了openjdk devel包裹 sudo yum install java 1 7 0 openjdk devel x86 64 但是 jstack 引发了异常j
  • 查找并删除超过 x 天的文件或文件夹

    我想删除超过 7 天的文件和文件夹 所以我尝试了 17 07 14 email protected cdn cgi l email protection find tmp mindepth 1 maxdepth 1 ctime 7 exec
  • 使用 --prof 选项创建多个日志文件而不是一个 v8.log 的节点

    我正在尝试使用 prof 选项来分析我的 Node 应用程序 但我发现不是一个单一的 v8 log 文件 而是使用诸如isolate 0x9582b40 v8 log isolate 0xa1cab78 v8 6049 等前缀创建的多个文件
  • 隐式声明“gets”

    据我所知 隐式声明 通常意味着该函数必须在调用之前放置在程序的顶部 或者我需要声明原型 然而 gets应该在stdio h文件 我已包含 有没有什么办法解决这一问题 include

随机推荐

  • Redis主从连接失败 connected_slaves:0

    进行主从连接配置时 主服务器使用info replication查到的 connected slaves数一直是0 原因是主服务器设置了密码 找到从服务器的配置文件redis conf 在配置文件中找到 masterauth
  • python如何做敏感度分析,使用SALib工具箱从测量数据进行Python敏感性分析

    I would like to understand how to use the SALib python toolbox to perform a Sobol sensitivity analysis to study paramete
  • IDEA 代码提交前流程及提交日志模板化

    前言 在开发大型项目时 通常都是由团队来进行开发 此时 每个人有每个人的代码编写风格和提交习惯 如果放任自由发挥 那么代码质量和代码提交日志就难免风格各异 导致项目代码质量难以保持统一 针对这一问题 往往公司在以项目组进行开发时 在进入正式
  • [转载]Python正则表达式匹配反斜杠'\'问题

    在学习Python正则式的过程中 有一个问题一直困扰我 如何去匹配一个反斜杠 即 一 引入 在学习了Python特殊字符和原始字符串之后 我觉得答案应该是这样的 1 普通字符串 2 原始字符串 r 但事实上在提取诸如 3 8 反斜杠之前的数
  • 高速PCB电路板的信号完整性设计

    目录 高速PCB电路板的信号完整性设计 1信号完整性基本理论 1 1 信号完整性定义 1 2影响信号完整性的主要因素 2高速数据采集系统 3 信号完整性设计 3 1电路板叠层设计 3 2电路板布局设计 3 3电路板布线设计 一 信号完整性是
  • 编译语言的编译和脚本语言的解释

    编译语言的编译和脚本语言的解释 编译语言和脚本语言 这个博主看了几篇帖子 觉得Jonny工作室的这篇文章解释的最简单明了 联想之间之前写的程序 大胆给一点自己的看法 如有不对还望指正 编译语言 脚本语言 c c python 题目出现编译语
  • 智能运维 VS 传统运维|AIOps服务管理解决方案全面梳理

    云智慧 AIOps 社区是由云智慧发起 针对运维业务场景 提供算法 算力 数据集整体的服务体系及智能运维业务场景的解决方案交流社区 该社区致力于传播 AIOps 技术 旨在与各行业客户 用户 研究者和开发者们共同解决智能运维行业技术难题 推
  • java开发Demo~微信扫码支付,java开发示例

    开发所需工具类 以上工具类以上传到我的资源 下载地址 http download csdn net download han xiaoxue 10184832 开发所需jar 具体的代码不贴了 说明下PayConfigUtil中的参数 AP
  • CMake详细使用

    1 CMake简介 CMake是一个用于管理源代码的跨平台构建工具 可以方便地根据目标平台和编译工具产生对应的编译文件 主要用于C C 语言的构建 但是也可以用于其它编程语言的源代码 如同使用make命令工具解析Makefile文件一样 c
  • 百度群组链接分享 - 铁人圈子

    百度网盘群组链接分享 铁人圈子 铁人圈子 tierenpan com 是一个分享百度网盘群组的发布平台 可以在铁人圈子上实时分享你的群组链接 并且和其他网友互动交流分享资源 群组分享 百度群组链接分享 地址 https www tieren
  • 58道Vue常见面试题集锦,涵盖入门到精通

    1 vue优点 答 轻量级框架 只关注视图层 是一个构建数据的视图集合 大小只有几十 kb 简单易学 国人开发 中文文档 不存在语言障碍 易于理解和学习 双向数据绑定 保留了 angular 的特点 在数据操作方面更为简单 组件化 保留了
  • vue 项目首页加载速度优化以及解决首页白屏问题

    前言 最近再接手一个vue项目的时候 公司运营部就说首页加载要10秒以上时间 这谁能忍受 老板也说时间太久 技术部老大说之前的同事优化过一次 时间还是这么久 重担就落在我身上了 于是我就开始着手优化 最终的结果呢就是优化到了2秒以内加载出来
  • python中dtype的使用规范_Python numpy.dtype() 使用实例

    The following are code examples for showing how to use They are extracted from open source Python projects You can vote
  • Mybatis执行过程源码解析

    使用Mybatis执行查询sql代码示例 SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder build Resources getResourceAsReade
  • 修改Jenkins以Root用户运行

    简单操作如下 vim etc sysconfig jenkins JENKINS USER root chown R root root var lib jenkins chown R root root var cache jenkins
  • Linux查看文件及文件夹大小

    du sh 查看当前目录下各个文件及目录占用空间大小 du sh 查看当前目录的总大小 df h 查看系统中文件的使用情况 Size 分割区总容量 Used 已使用的大小 Avail 剩下的大小 Use 使用的百分比 Mounted on
  • Uiautomator2

    https github com openatx uiautomator2 官方文档 第一步 先准备一台开启了开发者选项的安卓手机 连接上电脑 确保执行adb devices可以看到连接上的设备 不要开启charles 否则会导致下载失败
  • Window触发器和Delta触发器在大数据处理中的应用

    大数据处理是指处理海量数据的技术和方法 在大数据处理中 窗口触发器 Window Trigger 和Delta触发器 Delta Trigger 是常用的工具 用于按照一定的规则触发数据处理操作 本文将介绍这两种触发器的概念 应用场景 并给
  • 使用java实现http多线程下载

    下载工具我想没有几个人不会用的吧 前段时间比较无聊 花了点时间用java写了个简单的http多线程下载程序 纯粹是无聊才写的 只实现了几个简单的功能 而且也没写界面 今天正好也是一个无聊日 就拿来写篇文章 班门弄斧一下 觉得好给个掌声 不好
  • linux下通过V4L2驱动USB摄像头

    目录 文章目录 目录 前言 v4l2 解析 v4l2 介绍 应用程序通过 V4L2 接口采集视频数据步骤 相关结构体解析 总结 参考链接 前言 在移植罗技C270摄像头到6818的过程中 内核已经检测到了USB摄像头 但是直接用OpenCV