在之前的文章中研究过mac上虚拟摄像头的开发,主体思想就是借用obs的驱动,然后我们只要负责给驱动喂正确的数据就行了,那么同样的想法我在windows上复刻了出来。
OBS 虚拟摄像头 windows版
- 首先,最新的git地址是https://github.com/Fenrirthviti/obs-virtual-cam,
- 整个项目依赖于ffmpeg,所以自己编译的话,需要先编译ffmpeg,如果不想编译ffmpeg,那就使用vcpkg,如果连 obs-virtual-cam都懒得编译,那就直接下载release。
- 按照他的readme,安装插件,首先把插件放到c盘(其他盘没试过,只是怕放其他盘会被我误删),然后一定要注意,64位的dll不是那么重要,zoom必须在32位的dll注册以后才能找到驱动。
- 如果按照他的命令,你会发现,这个插件给你注册了4个虚拟摄像头,所以,按照我的命令:
regsvr32 /n /i:"1" "C:\OBS-Virtualcam-2.0.5-Windows\bin\32bit\obs-virtualsource.dll"
- 不想要的话卸载命令:
regsvr32 \u "C:\OBS-Virtualcam-2.0.5-Windows\bin\32bit\obs-virtualsource.dll"
- 打开zoom或者腾讯会议,你会发现,摄像头列表中多了一个
如何把图像传给虚拟摄像头
- 查看源码结构,virtual-source就是我们的虚拟摄像头,virtual-output的作用就是从Obs中获取数据后推送给虚拟摄像头的。
- 阅读virutal-ouput可知,核心思想就是建立一个queue,然后往queue里面push数据,从原理上来说,其实核心在于文件映射共享内存(CreateFileMappingA),这里不用太关心。
- 看代码虚拟摄像头能支持多种格式,不过我们不必冒险,还是使用uyuv422,使用以下命令获取yuv数据。
ffmpeg -i video.mp4 -pix_fmt uyvy422 output.yuv
代码实现
#include <stdio.h>
#include "../queue/share_queue_write.h"
#define HEIGHT 480
#define WIDTH 640
#define BUFSIZE WIDTH*HEIGHT*2
int main(int argc, char* argv[]){
bool start = false;
share_queue video_queue;
uint64_t interval = static_cast<int64_t>(1000000000 / 30);
int nb = 0;
uint8_t buffer[BUFSIZE];
uint32_t linesize[3] = {
WIDTH*2,0,0};
uint8_t* data[3] = {
nullptr,nullptr,nullptr};
data[0] = buffer;
start = shared_queue_create(&video_queue,ModeVideo, AV_PIX_FMT_UYVY422, WIDTH, HEIGHT,interval, 10);
//shared_queue_set_delay(&video_queue,0);
FILE * fp = fopen("d://output.yuv","rb+");
int time = 0;
while( (nb = fread(buffer, WIDTH * HEIGHT *2,1,fp))>0){
shared_queue_push_video(&video_queue, linesize, WIDTH, HEIGHT, data, time);
time += 33;
Sleep(33);
}
fclose(fp);
shared_queue_write_close(&video_queue);
}
- HEIGHT,WIDTH需要对应生成的YUV视频的长宽。
- 直接引用 “share_queue_write.h” 会报, “libavutil/pixfmt.h”, "libavutil/samplefmt.h"两个文件找不到,这两个文件是ffm