Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Query] Will this driver works for android as well? #330

Closed
Learner379 opened this issue Aug 4, 2020 · 10 comments
Closed

[Query] Will this driver works for android as well? #330

Learner379 opened this issue Aug 4, 2020 · 10 comments

Comments

@Learner379
Copy link

Hi,

I am new to this, Can anybody please share me the exact steps to create the virtual camera device/loop back device in android.

Thank you

@umlaeute
Copy link
Owner

umlaeute commented Aug 9, 2020

try it out ;-)
you will need the kernel-headers for the exact version of your target system to compile the module.
also, i'm pretty sure (but have no idea, tbh) that from a security standpoint you cannot just ship a kernel-module and insert it into some stock android image (kernel-space is way beyond sudo; so you need at least a rooted device to be able to load the driver).

apart from that: i don't see any immediate problems (but again: i have no idea)

@Learner379
Copy link
Author

Hi @umlaeute

Thanks for your reply.

I tried compiling the v4l2loopback driver on Android, able to load and create virtual camera nodes successfully. But when i try to capture a video from this virtual camera device, below issue is observed. Please find the steps, i am following.

1.insmod v4l2loopback.ko exclusive_caps=1 video_nr=23,24 => This is creating the /dev/video23 and /dev/video24 nodes.
2. ffmpeg -i /dev/video10 -f v4l2 -pix_fmt yuv420p /dev/video23 => using ffmpeg cmd, am feeding USB camera(/dev/video10) on to the virtual camera node.
3. ffmpeg -f v4l2 -i /dev/video23 -vframes 1 /sdcard/test.jpeg => Able to capture the single frame jpeg image from virtual camra node as well.
4. But capturing a video or feeding this virtual camera node on to the another virtual camera node is failing with below error.

ffmpeg -i /dev/video23 -f v4l2 -pix_fmt yuv420p /dev/video24
ffmpeg version n3.0.1 Copyright (c) 2000-2016 the FFmpeg developers
built with gcc 4.8 (GCC)
configuration: --target-os=linux --cross-prefix=/home/vagrant/SourceCode/ffmpeg-android/toolchain-android/bin/arm-linux-androideabi- --arch=arm --cpu=cortex-a8 --enable-runtime-cpudetect --sysroot=/home/vagrant/SourceCode/ffmpeg-android/toolchain-android/sysroot --enable-pic --enable-libx264 --enable-libass --enable-libfreetype --enable-libfribidi --enable-libmp3lame --enable-fontconfig --enable-pthreads --disable-debug --disable-ffserver --enable-version3 --enable-hardcoded-tables --disable-ffplay --disable-ffprobe --enable-gpl --enable-yasm --disable-doc --disable-shared --enable-static --pkg-config=/home/vagrant/SourceCode/ffmpeg-android/ffmpeg-pkg-config --prefix=/home/vagrant/SourceCode/ffmpeg-android/build/armeabi-v7a --extra-cflags='-I/home/vagrant/SourceCode/ffmpeg-android/toolchain-android/include -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fno-strict-overflow -fstack-protector-all' --extra-ldflags='-L/home/vagrant/SourceCode/ffmpeg-android/toolchain-android/lib -Wl,-z,relro -Wl,-z,now -pie' --extra-libs='-lpng -lexpat -lm' --extra-cxxflags=
libavutil 55. 17.103 / 55. 17.103
libavcodec 57. 24.102 / 57. 24.102
libavformat 57. 25.100 / 57. 25.100
libavdevice 57. 0.101 / 57. 0.101
libavfilter 6. 31.100 / 6. 31.100
libswscale 4. 0.100 / 4. 0.100
libswresample 2. 0.101 / 2. 0.101
libpostproc 54. 0.100 / 54. 0.100
[video4linux2,v4l2 @ 0xeff24000] ioctl(VIDIOC_DQBUF): Invalid argument
Input #0, video4linux2,v4l2, from '/dev/video23':
Duration: N/A, bitrate: 110592 kb/s
Stream #0:0: Video: rawvideo (I420 / 0x30323449), yuv420p, 640x480, 110592 kb/s, 30 fps, 30 tbr, 1000k tbn, 1000k tbc
Output #0, v4l2, to '/dev/video24':
Metadata:
encoder : Lavf57.25.100
Stream #0:0: Video: rawvideo (I420 / 0x30323449), yuv420p, 640x480, q=2-31, 200 kb/s, 30 fps, 30 tbn, 30 tbc
Metadata:
encoder : Lavc57.24.102 rawvideo
Stream mapping:
Stream #0:0 -> #0:0 (rawvideo (native) -> rawvideo (native))
Press [q] to stop, [?] for help
[video4linux2,v4l2 @ 0xeff24000] ioctl(VIDIOC_DQBUF): Invalid argument
/dev/video23: Invalid argument
frame= 1 fps=0.0 q=-0.0 Lsize=N/A time=00:00:00.03 bitrate=N/A speed=0.599x
video:450kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown

Can you please help me in resolving this error.

Thanks.

@fan3k
Copy link

fan3k commented Aug 1, 2021

Hey @Learner379 and you make this? How to? I need to replace a photo.

@Learner379
Copy link
Author

Hey @fan3k ,

Looks like the ffmpeg binary which I was using in android was buggy, as I was not able to stream physical usb camera also. So, I tried adding virtual camera node in to the camerHAL to make it work with the camera applications, but was not succeeded here also.

Please let me know if you have any inputs. And also what is the exact issue which you are facing?

@Learner379
Copy link
Author

@umlaeute , Did you try to make this repo work on Android?

@deeox
Copy link

deeox commented Sep 9, 2021

@Learner379 Can you please provide the steps to took to compile the kernel module for android? Trying to make this work on Pixel 5.

@rediceli
Copy link

rediceli commented Sep 27, 2021

@deeox

Build v4l2loopback for android need the kernel source (or headers & symbols) use to build your android image.
A Hard & Hack way I did on my device (The chance of success is small):

  1. Download kernel source which fix your android kernel version. Use vendor's kernel source if you can.
  2. Get the kernel config from device ( /proc/config.gz). If not exists, FAIL & STOP;
  3. Get the boot.img from device: try to find it at /dev/block/by-name. If not found, FAIL & STOP;
  4. Use unboot to get kernel from boot.img (boot.img-kernel), If fail, STOP;
  5. Use extract-symvers to get the 'Module.symvers' which need to build the external module of the kernel. if fail, STOP
  6. Prepare kernel:
cd kernel-source-dir
cat  your_config_gz_dir/config.gz > .config
make silentoldconfig prepare headers_install scripts
cp what_your_module_symvers_is/Module.symvers .
  1. build v4l2loopback:
cd v4l2loopback
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- M=`pwd` -C <YOUR_KERNEL_SOURCE_DIR> modules

or 

make ARCH=arm CROSS_COMPILE=arm-linux-gnu- M=`pwd` -C <YOUR_KERNEL_SOURCE_DIR> modules
  1. May still fail if the kernel is signed or some symbol not match ( because of vendor's patch or missing files etc.)

I did all upper steps success BUT the Android9 (on my rockchip board) not recognize v4l2loopback virtual camera as a system camera. Another virtual camera solution akvcam work, but not support compress H264 format.

Still working in progress...

@rediceli
Copy link

According to the android souce (hardware/interfaces/camera/device/3.4/default/ExternalCameraDevice.cpp), the V4L2 video device must be act as a VIDEO_CAPTURE device and support V4L2_PIX_FMT_MJPEG or V4L2_PIX_FMT_YUYV once it first connected (and never check again). So, the current v4l2loopback can not support android (to use as a camera).

To fix this, I patch the source with:

  1. Set default video caps to V4L2_PIX_FMT_YUYV;
  2. set keep_format=1 and ready_for_capture=1 by default;

Now, the camera APP detect the virtual device (without crash), but when I write YUYV422 stream, camera read nothing

diff --git a/v4l2loopback.c b/v4l2loopback.c
index 9da2508..e0ec3a6 100644
--- a/v4l2loopback.c
+++ b/v4l2loopback.c
@@ -207,7 +207,7 @@ static const struct v4l2_ctrl_config v4l2loopback_ctrl_keepformat = {
        .min    = 0,
        .max    = 1,
        .step   = 1,
-       .def    = 0,
+       .def    = 1,
        // clang-format on
 };
 static const struct v4l2_ctrl_config v4l2loopback_ctrl_sustainframerate = {
@@ -2030,6 +2030,21 @@ static void timeout_timer_clb(unsigned long nr)
        spin_unlock(&dev->lock);
 }
 
+static int set_default_format(struct v4l2_loopback_device *dev)
+{
+       //const struct v4l2l_format *format = &formats[3]; // V4L2_PIX_FMT_RGB24, 24 bpp RGB, be
+       //const struct v4l2l_format *format = &formats[1]; // V4L2_PIX_FMT_RGB32, 32 bpp RGB, be
+       const struct v4l2l_format *format = &formats[11]; // V4L2_PIX_FMT_YUYV,4:2:2, packed, YUYV
+       struct v4l2_pix_format *pix_fmt = &dev->pix_format;
+
+       pix_fmt->width = 800;
+       pix_fmt->height = 600;
+       pix_format_set_size(pix_fmt, format, 800, 600);
+       pix_fmt->pixelformat = format->fourcc;
+       pix_fmt->colorspace = V4L2_COLORSPACE_SRGB;
+       return 0;
+}
+
 /* init loopback main structure */
 #define DEFAULT_FROM_CONF(confmember, default_condition, default_value)        \
        ((conf) ?                                                              \
@@ -2207,7 +2222,9 @@ v4l2_loopback_add(struct v4l2_loopback_config *conf)
                V4L2_COLORSPACE_SRGB; /* do we need to set this ? */
        dev->pix_format.field = V4L2_FIELD_NONE;
 
+       set_default_format(dev);
        dev->buffer_size = PAGE_ALIGN(dev->pix_format.sizeimage);
+       dev->pix_format.sizeimage = dev->buffer_size;
        dprintk("buffer_size = %ld (=%u)\n", dev->buffer_size,
                dev->pix_format.sizeimage);
        err = allocate_buffers(dev);
@@ -2224,6 +2241,7 @@ v4l2_loopback_add(struct v4l2_loopback_config *conf)
                goto out_free_device;
        }
        v4l2loopback_create_sysfs(dev->vdev);
+       dev->ready_for_capture = 1;
 
        return dev;

@deeox
Copy link

deeox commented Oct 1, 2021

@rediceli Thanks a lot for explaining everything clearly, I'll try the above and get back

@ali6836
Copy link

ali6836 commented Apr 25, 2022

According to the android souce (hardware/interfaces/camera/device/3.4/default/ExternalCameraDevice.cpp), the V4L2 video device must be act as a VIDEO_CAPTURE device and support V4L2_PIX_FMT_MJPEG or V4L2_PIX_FMT_YUYV once it first connected (and never check again). So, the current v4l2loopback can not support android (to use as a camera).

To fix this, I patch the source with:

  1. Set default video caps to V4L2_PIX_FMT_YUYV;
  2. set keep_format=1 and ready_for_capture=1 by default;

Now, the camera APP detect the virtual device (without crash), but when I write YUYV422 stream, camera read nothing

diff --git a/v4l2loopback.c b/v4l2loopback.c
index 9da2508..e0ec3a6 100644
--- a/v4l2loopback.c
+++ b/v4l2loopback.c
@@ -207,7 +207,7 @@ static const struct v4l2_ctrl_config v4l2loopback_ctrl_keepformat = {
        .min    = 0,
        .max    = 1,
        .step   = 1,
-       .def    = 0,
+       .def    = 1,
        // clang-format on
 };
 static const struct v4l2_ctrl_config v4l2loopback_ctrl_sustainframerate = {
@@ -2030,6 +2030,21 @@ static void timeout_timer_clb(unsigned long nr)
        spin_unlock(&dev->lock);
 }
 
+static int set_default_format(struct v4l2_loopback_device *dev)
+{
+       //const struct v4l2l_format *format = &formats[3]; // V4L2_PIX_FMT_RGB24, 24 bpp RGB, be
+       //const struct v4l2l_format *format = &formats[1]; // V4L2_PIX_FMT_RGB32, 32 bpp RGB, be
+       const struct v4l2l_format *format = &formats[11]; // V4L2_PIX_FMT_YUYV,4:2:2, packed, YUYV
+       struct v4l2_pix_format *pix_fmt = &dev->pix_format;
+
+       pix_fmt->width = 800;
+       pix_fmt->height = 600;
+       pix_format_set_size(pix_fmt, format, 800, 600);
+       pix_fmt->pixelformat = format->fourcc;
+       pix_fmt->colorspace = V4L2_COLORSPACE_SRGB;
+       return 0;
+}
+
 /* init loopback main structure */
 #define DEFAULT_FROM_CONF(confmember, default_condition, default_value)        \
        ((conf) ?                                                              \
@@ -2207,7 +2222,9 @@ v4l2_loopback_add(struct v4l2_loopback_config *conf)
                V4L2_COLORSPACE_SRGB; /* do we need to set this ? */
        dev->pix_format.field = V4L2_FIELD_NONE;
 
+       set_default_format(dev);
        dev->buffer_size = PAGE_ALIGN(dev->pix_format.sizeimage);
+       dev->pix_format.sizeimage = dev->buffer_size;
        dprintk("buffer_size = %ld (=%u)\n", dev->buffer_size,
                dev->pix_format.sizeimage);
        err = allocate_buffers(dev);
@@ -2224,6 +2241,7 @@ v4l2_loopback_add(struct v4l2_loopback_config *conf)
                goto out_free_device;
        }
        v4l2loopback_create_sysfs(dev->vdev);
+       dev->ready_for_capture = 1;
 
        return dev;

Have you attempted to create video nodes, move the original video nodes for the original cameras, and then link the v4l2loopback video nodes to the positions where the original nodes were?
For example, if my back camera was /dev/video0, move it to /dev/video10 and then create a loopback device at /dev/video11 and link it to /dev/video0.

Repository owner locked and limited conversation to collaborators Apr 12, 2023
@umlaeute umlaeute converted this issue into discussion #537 Apr 12, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Projects
None yet
Development

No branches or pull requests

6 participants