Android虚拟摄像头

Android虚拟摄像头

最开始想在Redroid上实现使用USB摄像头功能,但尝试了很多方法后也没成功。

外网有大佬给树莓派4B适配了安卓系统,测试了一下,可以直接使用USB摄像头,于是照着代码抄,但是Redroid就是用不了USB摄像头。(第三方USB摄像头APP可以调用摄像头,系统相机无法调用,猜测和内核、显卡有关系)

折腾一段时间后,尝试在树莓派4B上实现虚拟摄像头。网上能搜到的大多是使用v4l2loopback这个内核模块来创建虚拟设备,于是我也尝试使用这个模块。

编译这个模块就踩坑了,死活编译不了,还好一番搜索后发现有其他开源手机内核内置了这个模块,把makefile抄过来就编译成功了。

https://github.com/droidian-devices/linux-android-xiaomi-lavender/tree/droidian/drivers/media/v4l2loopback

再然后需要使用ffmpeg给v4l2loopback喂数据,经测试后,并不像网上说的可以传yuv420p数据,而是需要mjpeg格式,但ffmpeg始终报错。。。

搜索后发现是ffmpeg版本过低,于是开启编译ffmpeg的支线,好在资料比较多,成功编译了arm32位的版本。(64位没成功,32位可以凑合用。)

然后又出现如下错误:

1
2
3
11-07 06:52:40.536  1998  2000 W ExtCamDevSsn@3.4: setV4l2FpsLocked: device does not support V4L2_CAP_TIMEPERFRAME
11-07 06:52:40.536 1998 2000 E ExtCamDevSsn@3.4: configureV4l2StreamLocked: VIDIOC_REQBUFS expected 4 buffers, got 2 instead
11-07 06:52:40.536 1998 2000 E ExtCamDevSsn@3.4: V4L configuration failed!, format:MJPG, w 1280, h 720

解决方案就是修改内核启动参数,将v4l2loopback.max_buffers的设置大一些。

1
console=ttyS0,115200 no_console_suspend root=/dev/ram0 rootwait androidboot.hardware=rpi4 androidboot.selinux=permissive v4l2loopback.devices=2 v4l2loopback.video_nr=0,1 v4l2loopback.card_label=Droidian_back,Droidian_front v4l2loopback.exclusive_caps=0,0 v4l2loopback.max_buffers=5

再次出现报错信息DQBUF fails: Invalid argument

1
2
3
4
11-07 06:43:31.755  1588  1591 I ExtCamDevSsn@3.4: configureV4l2StreamLocked: V4L2 buffer size is 3686400
11-07 06:43:31.755 1588 1591 W ExtCamDevSsn@3.4: setV4l2FpsLocked: device does not support V4L2_CAP_TIMEPERFRAME
11-07 06:43:31.757 1588 1591 E ExtCamDevSsn@3.4: configureV4l2StreamLocked: DQBUF fails: Invalid argument
11-07 06:43:31.757 1588 1591 E ExtCamDevSsn@3.4: V4L configuration failed!, format:MJPG, w 1280, h 720

解决方案,删除函数static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)中的以下代码:

1
2
3
4
5
if (!(dev->buffers[index].buffer.flags &
V4L2_BUF_FLAG_MAPPED)) {
dprintk("trying to return not mapped buf[%d]\n", index);
return -EINVAL;
}
1
2
/data/local/tmp/ffmpeg -re -stream_loop -1 -i /data/local/tmp/test.mp4 -c:v mjpeg -f v4l2 /dev/video0
kill -9 `pidof android.hardware.camera.provider@2.5-external-service`