Windows远程桌面实现之十五:投射浏览器摄像头到xdisp_virt以及再次模拟摄像头(二, Linux虚拟摄像头驱动)

                                                       by fanxiushu  2024-12-11 转载或引用请注明原作者。
续上文,
间隔的时间有点长,因此先简单回忆上文描述的内容。
上文主要是阐述在浏览器中如何通过 javascript脚本语言,通过WebRTC通讯方式,
把浏览器中的摄像头图像传输到 xdisp_virt程序,然后再通过xdisp_virt丰富的扩展功能把浏览器摄像头共享出去。

本文将主要阐述如何再进一步,把浏览器摄像头传递到xdisp_virt的图像再次模拟成电脑的摄像头。
为了让大家更明白本文以及上文在讲什么,我们还是先来一段演示视频和示列图:
 

手机浏览器摄像头映射到电脑端并且再次模拟成电脑摄像头



xdisp_virt程序的配置界面图如下:



更多和更详细的演示视频,可以去我的GITHUB对应项目下去查看:
GitHub - fanxiushu/xdisp_virt: xfsredir file system

本文主要是阐述如何实现电脑系统的虚拟摄像头驱动,
电脑系统以windows和linux为主,macOS因为驱动接触不多,所以目前并没实现对应的摄像头驱动。
windows平台的虚拟摄像头,以前的文章,以及以以前的文章都阐述了,讲的也挺多,
而且还是阐述的各种方式的,多种花样的实现windows平台下的摄像头驱动,因此这里也就不再罗嗦。
本文主要阐述linux平台下,实现V4L2框架的虚拟摄像头驱动。

V4L2驱动框架在linux系统中的地位类似于AVStream驱动框架在windows平台中的地位,都是实现流媒体的核心框架类。
但是V4L2对应的应用层接口显得非常原始,基本使用ioctl与驱动交互;
并不像windows平台做了各种封装,已经看不到原始的ioctl与驱动交互了。

我们来看看应用层如何ioctl来打开并且使用摄像头,这有助于我们了解V4L2驱动框架的大致运作过程。

1, 打开摄像头,通常是
    int handle =open( "/dev/videoXX“, O_RDWR) , XX是具体的数字,
    ioctl(handle, VIDIOC_QUERYCAP, &vcap);
    通过VIDIOC_QUERYCAP命令获取设备的属性,判断是不是摄像头,以及摄像头名字等,
    类似 VIDIOC_XXXX 的命令是非常多的,基本构成了V4L2 的主旋律。

2,查询图像格式,查询分辨率,设置图像格式等前期预备操作,
      v4l2_format  format; //
      memset(&format, 0, sizeof(format));
      format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
      ioctl(handle, VIDIOC_G_FMT, &format);    ///VIDIOC_G_FMT查询图像格式
      format.fmt.pix.height =height;
      format.fmt.pix.width = width;  设置自己期望得宽高,其他参数保持不变
      ioctl(handle, VIDIOC_S_FMT, &format); ///设置
      ioctl(handle, VIDIOC_G_FMT, &format); /再次获取,因为我们期望的宽高与摄像头实际值可能有出入。
      ...... 还可以有许多其他参配置,比如 VIDIOC_ENUM_FRAMESIZES查询所有分辨率,VIDIOC_ENUM_FMT,
             VIDIOC_S_PARM, VIDIOC_S_PARM, 等等,反正是非常多,估计这些参数命令得有十多个。

3,分配内存队列,用于图像数据传输,通常使用映射内存。
      int      len_arrar[4];
      char*  buf_array[4];    //用来保存从驱动映射到应用层的内存地址。
      struct v4l2_requestbuffers req;
      req.count = 4;
      req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
      req.memory = V4L2_MEMORY_MMAP;
      ioctl(handle, VIDIOC_REQBUFS, &req); VIDIOC_REQBUFS命令分配映射内存,req.count返回实际分配到多少个内存块, 
      for (int i = 0; i < req.count; ++i) {
            struct v4l2_buffer buffer;
            memset(&buffer, 0, sizeof(buffer));
            buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            buffer.memory = V4L2_MEMORY_MMAP;
            buffer.index = i;
            ioctl(handle, VIDIOC_QUERYBUF, &buffer) ; / 查询buffer信息,用于map映射内存到应用层。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨中风华

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值