Giter VIP home page Giter VIP logo

uvc-gadget's People

Contributors

climberhunt avatar dgsiegel avatar peterbay avatar rcarmo avatar rthpjm avatar wlhe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

uvc-gadget's Issues

UVC: Possible USB shutdown requested from Host, seen during VIDIOC_DQBUF

We are using zynq Ultrascale + MPSoC with custom board.
Our board has 2 USB ports(Host 2.0 and device 3.0), 2 SDI(one input and another output).
Kernel version on board is 4.19.0 and In host PC 5.4.0-58-generic.
Final project according to customers requirement is Streaming 1080p video taking input from SDI and taking output from USB(device).
Currently We are trying with connecting C922 Pro Stream Webcam to USB(host) port.This creates /dev/video0 node.
Then modprobe g_webcam. This creates /dev/video1.
Using the application https://github.com/peterbay/uvc-gadget
At host side /dev/video0 is created.
When I try to display using application such as guvcview, at the device side, getting below attached log.
I need some more input so that I can move forward with this project.
USBGITLOG.txt
host

Mac OS 12.0.1 Monterey fails to detect the device

This issue has been worked on over at the showmewebcam project, and has now been resolved (see Issue #164).

It turns out that Monterey has a different behaviour to previous versions of Mac OS, and is more sensitive to the configuration numbering of uvc-gadget.

In multi-gadget.sh the config is currently written to the configfs folder $GADGET_PATH/configs/c.2, however this is the only configuration. Monterey seems to expect the configuration to be numbered starting at one.
Therefore the config folder should be: $GADGET_PATH/configs/c.1

It looks like a simple bounds issue in Monterey.
Currently uvc-gadget presents the configuration as effectively "number 2 of 1 configuration". This gives Monterey a headache! By amending the folder to c.1 uvc-gadget then presents the configuration as "number 1 of 1 configuration" and Monterey is happy.

Don't include system's Linux tree when compiling uvc-gadget

This patch would fix it:

diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,7 @@
 CROSS_COMPILE	?= 
-ARCH		?= x86
-KERNEL_DIR	?= /usr/src/linux
 
 CC		:= $(CROSS_COMPILE)gcc
-KERNEL_INCLUDE	:= -I$(KERNEL_DIR)/include -I$(KERNEL_DIR)/arch/$(ARCH)/include
-CFLAGS		:= -W -Wall -g $(KERNEL_INCLUDE)
+CFLAGS		:= -W -Wall -g
 LDFLAGS		:= -g
 
 all: uvc-gadget
``

[IDEA][PI] Screen capture through UVC device

So I had an idea... what if we could send the screen through the UVC gadget.
I have the PoC working, but I only get 1 FPS... If someone could point me in the right direction I ll be greatly gratefull.

#!/bin/bash

sudo modprobe v4l2loopback video_nr=100 exclusive_caps=1
ffmpeg -f x11grab -i :0.0+0,0 -vcodec mjpeg -pix_fmt yuv420p -f v4l2 /dev/video100 &
sleep 5
uvc-gadget -u /dev/video0 -v /dev/video100 -r 30 &

With this concept, the usb capture card wont be required. The pi could be connected to a pc via usb and get the image through vlc.
Additionally with the ethernet gadget we could also use x2x to control de device...

fails with 6.1.21+ on Raspberry Pi Zero W rev 1.1

During multi-gadget.sh the last line of that script fails:

ls /sys/class/udc > $GADGET_PATH/UDC results in: ls: write error: Device or resource busy

in dmesg I see: [ 80.470962] UDC core: pi4: couldn't find an available UDC or it's busy

that eventually leads to:

DEVICE_UVC: Device open failed: No such file or directory (2).

It does work with showmewebcam (which uses an older 5.10.11 kernel) and it fails with raspbian bullseye with kernel 6.1.21+ (6.1.34+ also fails).

brightness setting in camera.txt is being ignored

After writing /boot/camera.txt with

#Tweak the auto exposure bias
auto_exposure_bias=15
#Tweak the brightness
brightness=55

the auto_expose_bias value is being honoured, but not the brightness value.

# /usr/bin/v4l2-ctl -L

User Controls

             brightness 0x00980900 (int)    : min=0 max=100 step=1 default=50 value=50 flags=slider
[...]          
             auto_exposure_bias 0x009a0913 (intmenu): min=0 max=24 default=12 value=15
[...]

Any idea how to fix this problem?
In order to have the brightness at 55 after a reboot, I have to set it manually via /usr/bin/v4l2-ctl -c brightness=55 which seems to work until the next reboot.

This is the journalctl output:

Feb 07 15:50:57 piwebcam systemd[1]: Started Serial Getty on ttyAMA0.
Feb 07 15:50:58 piwebcam ifup[103]: ifup: can't open '/var/run/ifstate.new': No such file or directory
Feb 07 15:50:58 piwebcam systemd[1]: network.service: Main process exited, code=exited, status=1/FAILURE
Feb 07 15:50:58 piwebcam systemd[1]: network.service: Failed with result 'exit-code'.
Feb 07 15:50:58 piwebcam systemd[1]: Failed to start Network Connectivity.
Feb 07 15:50:58 piwebcam systemd[1]: Reached target Network.
Feb 07 15:50:58 piwebcam systemd[1]: Found device /dev/ttyGS0.
Feb 07 15:50:58 piwebcam systemd[1]: Started Serial Getty on ttyGS0.
Feb 07 15:50:58 piwebcam systemd[1]: Reached target Login Prompts.
Feb 07 15:50:58 piwebcam systemd[1]: Reached target Multi-User System.
Feb 07 15:50:58 piwebcam systemd[1]: Starting Update UTMP about System Runlevel Changes...
Feb 07 15:50:58 piwebcam systemd[1]: systemd-update-utmp-runlevel.service: Succeeded.
Feb 07 15:50:58 piwebcam systemd[1]: Started Update UTMP about System Runlevel Changes.
Feb 07 15:50:58 piwebcam systemd[1]: Startup finished in 2.180s (kernel) + 6.930s (userspace) = 9.110s.
Feb 07 15:50:58 piwebcam kernel: configfs-gadget gadget: uvc: uvc_function_bind()
Feb 07 15:50:58 piwebcam kernel: dwc2 20980000.usb: bound driver configfs-gadget
Feb 07 15:50:59 piwebcam piwebcam[170]: Found camera.txt, applying settings
Feb 07 15:50:59 piwebcam piwebcam[182]: Setting auto_exposure_bias -> 15
Feb 07 15:50:59 piwebcam piwebcam[190]: Setting brightness -> 55
Feb 07 15:50:59 piwebcam kernel: dwc2 20980000.usb: new device is high-speed
Feb 07 15:50:59 piwebcam kernel: dwc2 20980000.usb: new address 18
Feb 07 15:50:59 piwebcam kernel: configfs-gadget gadget: high-speed config #2: c
Feb 07 15:50:59 piwebcam kernel: configfs-gadget gadget: uvc: uvc_function_set_alt(0, 0)
Feb 07 15:50:59 piwebcam kernel: configfs-gadget gadget: uvc: reset UVC Control
Feb 07 15:50:59 piwebcam kernel: configfs-gadget gadget: uvc: uvc_function_set_alt(1, 0)
Feb 07 15:50:59 piwebcam kernel: configfs-gadget gadget: uvc: uvc_function_set_alt(1, 0)
Feb 07 15:50:59 piwebcam kernel: configfs-gadget gadget: uvc: uvc_function_set_alt(1, 0)
Feb 07 15:50:59 piwebcam piwebcam[192]: CONFIGFS: Initial path: /sys/kernel/config/usb_gadget
Feb 07 15:50:59 piwebcam piwebcam[192]: CONFIGFS: UVC: format: 1, frame: 10, resolution: 1600x1200, bitrate: [153600000, 307200000]
Feb 07 15:50:59 piwebcam piwebcam[192]: CONFIGFS: UVC: format: 1, frame: 9, resolution: 1600x900, bitrate: [115200000, 230400000]
Feb 07 15:50:59 piwebcam piwebcam[192]: CONFIGFS: UVC: format: 1, frame: 8, resolution: 1536x864, bitrate: [106168320, 212336640]
Feb 07 15:50:59 piwebcam piwebcam[192]: CONFIGFS: UVC: format: 1, frame: 7, resolution: 1920x1080, bitrate: [165888000, 331776000]
Feb 07 15:50:59 piwebcam piwebcam[192]: CONFIGFS: UVC: format: 1, frame: 6, resolution: 1280x960, bitrate: [98304000, 196608000]
Feb 07 15:50:59 piwebcam piwebcam[192]: CONFIGFS: UVC: format: 1, frame: 5, resolution: 1280x720, bitrate: [73728000, 147456000]
Feb 07 15:50:59 piwebcam piwebcam[192]: CONFIGFS: UVC: format: 1, frame: 4, resolution: 1024x768, bitrate: [62914560, 125829120]
Feb 07 15:50:59 piwebcam piwebcam[192]: CONFIGFS: UVC: format: 1, frame: 3, resolution: 800x600, bitrate: [38400000, 76800000]
Feb 07 15:50:59 piwebcam piwebcam[192]: CONFIGFS: UVC: format: 1, frame: 2, resolution: 640x480, bitrate: [24576000, 49152000]
Feb 07 15:50:59 piwebcam piwebcam[192]: CONFIGFS: UVC: format: 1, frame: 1, resolution: 640x360, bitrate: [18432000, 36864000]
Feb 07 15:50:59 piwebcam piwebcam[192]: SETTINGS: Number of buffers requested: 2
Feb 07 15:50:59 piwebcam piwebcam[192]: SETTINGS: Video format: V4L2_PIX_FMT_MJPEG
Feb 07 15:50:59 piwebcam piwebcam[192]: SETTINGS: Show FPS: DISABLED
Feb 07 15:50:59 piwebcam piwebcam[192]: SETTINGS: IO method requested: USER_PTR
Feb 07 15:50:59 piwebcam piwebcam[192]: SETTINGS: UVC device name: /dev/video1
Feb 07 15:50:59 piwebcam piwebcam[192]: SETTINGS: V4L2 device name: /dev/video0
Feb 07 15:50:59 piwebcam piwebcam[192]: DEVICE_UVC: Opening /dev/video1 device
Feb 07 15:50:59 piwebcam piwebcam[192]: DEVICE_UVC: Device is 20980000.usb on bus gadget
Feb 07 15:50:59 piwebcam piwebcam[192]: DEVICE_V4L2: Opening /dev/video0 device
Feb 07 15:50:59 piwebcam piwebcam[192]: DEVICE_V4L2: Device is mmal service 16.1 on bus platform:bcm2835-v4l2
Feb 07 15:50:59 piwebcam piwebcam[192]: DEVICE_V4L2: Getting highest frame size: YUYV 4056x3040
Feb 07 15:50:59 piwebcam piwebcam[192]: DEVICE_V4L2: Getting highest frame size: MJPG 4056x3040
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2: Supported control Brightness (V4L2_CID_BRIGHTNESS = UVC_PU_BRIGHTNESS_CONTROL)
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2:   V4L2: min: 0, max: 100, step: 1, default: 50, value: 55
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2:   UVC: min: 0, max: 100, step: 1, default: 50, value: 55
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2: Supported control Contrast (V4L2_CID_CONTRAST = UVC_PU_CONTRAST_CONTROL)
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2:   V4L2: min: -100, max: 100, step: 1, default: 0, value: 0
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2:   UVC: min: 0, max: 200, step: 1, default: 100, value: 100
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2: Supported control Saturation (V4L2_CID_SATURATION = UVC_PU_SATURATION_CONTROL)
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2:   V4L2: min: -100, max: 100, step: 1, default: 0, value: 0
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2:   UVC: min: 0, max: 200, step: 1, default: 100, value: 100
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2: Supported control Red Balance (V4L2_CID_RED_BALANCE + V4L2_CID_BLUE_BALANCE = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL)
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2:   V4L2: min: 1, max: 7999, step: 1, default: 1000, value: 1000
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2:   UVC: min: 0, max: 7998, step: 1, default: 999, value: 999
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2: Supported control Power Line Frequency (V4L2_CID_POWER_LINE_FREQUENCY = UVC_PU_POWER_LINE_FREQUENCY_CONTROL)
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2:   V4L2: min: 0, max: 3, step: 1, default: 1, value: 1
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2:   UVC: min: 0, max: 3, step: 1, default: 1, value: 1
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2: Supported control Sharpness (V4L2_CID_SHARPNESS = UVC_PU_SHARPNESS_CONTROL)
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2:   V4L2: min: -100, max: 100, step: 1, default: 0, value: 0
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2:   UVC: min: 0, max: 200, step: 1, default: 100, value: 100
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2: Supported control Auto Exposure (V4L2_CID_EXPOSURE_AUTO = UVC_CT_AE_MODE_CONTROL)
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2:   V4L2: min: 0, max: 3, step: 1, default: 0, value: 0
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2:   UVC: min: 0, max: 3, step: 1, default: 0, value: 0
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2: Supported control Exposure Time, Absolute (V4L2_CID_EXPOSURE_ABSOLUTE = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL)
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2:   V4L2: min: 1, max: 10000, step: 1, default: 1000, value: 1000
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2:   UVC: min: 0, max: 9999, step: 1, default: 999, value: 999
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2: Supported control Exposure, Dynamic Framerate (V4L2_CID_EXPOSURE_AUTO_PRIORITY = UVC_CT_AE_PRIORITY_CONTROL)
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2:   V4L2: min: 0, max: 1, step: 1, default: 0, value: 0
Feb 07 15:50:59 piwebcam piwebcam[192]: V4L2:   UVC: min: 0, max: 1, step: 1, default: 0, value: 0
Feb 07 15:50:59 piwebcam piwebcam[192]: request uvc_fill_streaming_control: 0, 0
Feb 07 15:50:59 piwebcam piwebcam[192]: response: 1, 1
Feb 07 15:50:59 piwebcam piwebcam[192]: FRAME FORMAT: format: 1, frame: 1, resolution: 640x360, bitrate: [18432000, 36864000]
Feb 07 15:50:59 piwebcam piwebcam[192]: request uvc_fill_streaming_control: 0, 0
Feb 07 15:50:59 piwebcam piwebcam[192]: response: 1, 1
Feb 07 15:50:59 piwebcam piwebcam[192]: FRAME FORMAT: format: 1, frame: 1, resolution: 640x360, bitrate: [18432000, 36864000]
Feb 07 15:50:59 piwebcam piwebcam[192]: UVC: PROCESSING_UNIT - GET_INFO - UVC_PU_BRIGHTNESS_CONTROL
Feb 07 15:50:59 piwebcam piwebcam[192]: UVC: PROCESSING_UNIT - GET_MIN - UVC_PU_BRIGHTNESS_CONTROL
Feb 07 15:50:59 piwebcam piwebcam[192]: UVC: PROCESSING_UNIT - GET_MAX - UVC_PU_BRIGHTNESS_CONTROL
Feb 07 15:50:59 piwebcam piwebcam[192]: UVC: PROCESSING_UNIT - GET_RES - UVC_PU_BRIGHTNESS_CONTROL
Feb 07 15:51:11 piwebcam kernel: random: crng init done
Feb 07 15:51:11 piwebcam kernel: random: 7 urandom warning(s) missed due to ratelimiting
Feb 07 15:52:05 piwebcam login[133]: root login on 'ttyGS0'

I see, that the brightness is being set, but the output stays the same at 50.

v4l2-ctl -l

User Controls

                     brightness 0x00980900 (int)    : min=0 max=100 step=1 default=50 value=50 flags=slider
                       contrast 0x00980901 (int)    : min=-100 max=100 step=1 default=0 value=0 flags=slider
                     saturation 0x00980902 (int)    : min=-100 max=100 step=1 default=0 value=0 flags=slider
                    red_balance 0x0098090e (int)    : min=1 max=7999 step=1 default=1000 value=1000 flags=slider
                   blue_balance 0x0098090f (int)    : min=1 max=7999 step=1 default=1000 value=1000 flags=slider
                horizontal_flip 0x00980914 (bool)   : default=0 value=0
                  vertical_flip 0x00980915 (bool)   : default=0 value=0
           power_line_frequency 0x00980918 (menu)   : min=0 max=3 default=1 value=1
                      sharpness 0x0098091b (int)    : min=-100 max=100 step=1 default=0 value=0 flags=slider
                  color_effects 0x0098091f (menu)   : min=0 max=15 default=0 value=0
                         rotate 0x00980922 (int)    : min=0 max=360 step=90 default=0 value=0 flags=modify-layout
             color_effects_cbcr 0x0098092a (int)    : min=0 max=65535 step=1 default=32896 value=32896

Codec Controls

             video_bitrate_mode 0x009909ce (menu)   : min=0 max=1 default=0 value=0 flags=update
                  video_bitrate 0x009909cf (int)    : min=25000 max=25000000 step=25000 default=10000000 value=25000000
         repeat_sequence_header 0x009909e2 (bool)   : default=0 value=0
            h264_i_frame_period 0x00990a66 (int)    : min=0 max=2147483647 step=1 default=60 value=60
                     h264_level 0x00990a67 (menu)   : min=0 max=11 default=11 value=11
                   h264_profile 0x00990a6b (menu)   : min=0 max=4 default=4 value=4

Camera Controls

                  auto_exposure 0x009a0901 (menu)   : min=0 max=3 default=0 value=0
         exposure_time_absolute 0x009a0902 (int)    : min=1 max=10000 step=1 default=1000 value=1000
     exposure_dynamic_framerate 0x009a0903 (bool)   : default=0 value=0
             auto_exposure_bias 0x009a0913 (intmenu): min=0 max=24 default=12 value=15
      white_balance_auto_preset 0x009a0914 (menu)   : min=0 max=10 default=1 value=1
            image_stabilization 0x009a0916 (bool)   : default=0 value=0
                iso_sensitivity 0x009a0917 (intmenu): min=0 max=4 default=0 value=0
           iso_sensitivity_auto 0x009a0918 (menu)   : min=0 max=1 default=1 value=1
         exposure_metering_mode 0x009a0919 (menu)   : min=0 max=2 default=0 value=0
                     scene_mode 0x009a091a (menu)   : min=0 max=13 default=0 value=0

JPEG Compression Controls

            compression_quality 0x009d0903 (int)    : min=1 max=100 step=1 default=30 value=30

High CPU usage after capture on RPi Zero running showmewebcam

Problem Description:
The /opt/uvc-webcam/uvc-gadget -l -p 21 -b process keeps running and using more then 20% CPU after the host system finished capturing from the v4l2 device. CPU usage from top when connecting to the debug shell on the RPi Zero:

Before host started capture (idle):

Mem: 33600K used, 375412K free, 1516K shrd, 1108K buff, 16028K cached
CPU:   0% usr   2% sys   0% nic  97% idle   0% io   0% irq   0% sirq
Load average: 0.07 0.04 0.00 2/43 334
  PID  PPID USER     STAT   VSZ %VSZ %CPU COMMAND
  326   278 root     R     1880   0%   3% /opt/uvc-webcam/uvc-gadget -l -p 21 -b
  334   274 root     R     2756   1%   0% top
    1     0 root     S     7564   2%   0% {systemd} /sbin/init
   64     1 root     S     7520   2%   0% /usr/lib/systemd/systemd-udevd
   60     1 root     S     7104   2%   0% /usr/lib/systemd/systemd-journald
   93     1 dbus     S     5008   1%   0% /usr/bin/dbus-daemon --system --addres
   94     1 root     S     2756   1%   0% -sh
  274     1 root     S     2756   1%   0% -sh
  278     1 root     S     2628   1%   0% {start-webcam.sh} /bin/sh /opt/uvc-web
    8     2 root     SW       0   0%   0% [ksoftirqd/0]
   14     2 root     SW       0   0%   0% [kcompactd0]
   44     2 root     IW<      0   0%   0% [kworker/0:1H-kb]
  332     2 root     IW       0   0%   0% [kworker/0:0-eve]
  333     2 root     IW       0   0%   0% [kworker/0:1-eve]
    2     0 root     SW       0   0%   0% [kthreadd]
    5     2 root     IW       0   0%   0% [kworker/u2:0-ev]
    6     2 root     IW<      0   0%   0% [mm_percpu_wq]
    7     2 root     SW       0   0%   0% [rcu_tasks_trace]
    9     2 root     SW       0   0%   0% [kdevtmpfs]
   10     2 root     IW<      0   0%   0% [netns]

When host is capturing stream (streaming):

Mem: 34476K used, 374536K free, 1516K shrd, 1108K buff, 16028K cached
CPU:   5% usr  67% sys   0% nic  26% idle   0% io   0% irq   0% sirq
Load average: 0.70 0.28 0.10 2/43 335
  PID  PPID USER     STAT   VSZ %VSZ %CPU COMMAND
  335     2 root     RW       0   0%  35% [kworker/0:0-eve]
  326   278 root     S     2832   1%  29% /opt/uvc-webcam/uvc-gadget -l -p 21 -b
   39     2 root     SW<      0   0%   4% [vchiq-slot/0]
  277     2 root     IW       0   0%   3% [kworker/u2:2-mm]
  334   274 root     R     2756   1%   2% top
    8     2 root     SW       0   0%   0% [ksoftirqd/0]
    1     0 root     S     7564   2%   0% {systemd} /sbin/init
   64     1 root     S     7520   2%   0% /usr/lib/systemd/systemd-udevd
   60     1 root     S     7104   2%   0% /usr/lib/systemd/systemd-journald
   93     1 dbus     S     5008   1%   0% /usr/bin/dbus-daemon --system --addres
   94     1 root     S     2756   1%   0% -sh
  274     1 root     S     2756   1%   0% -sh
  278     1 root     S     2628   1%   0% {start-webcam.sh} /bin/sh /opt/uvc-web
   14     2 root     SW       0   0%   0% [kcompactd0]
   44     2 root     IW<      0   0%   0% [kworker/0:1H-kb]
  333     2 root     IW       0   0%   0% [kworker/0:1-eve]
   40     2 root     SW<      0   0%   0% [vchiq-recy/0]
   42     2 root     IW       0   0%   0% [kworker/0:2-eve]
    2     0 root     SW       0   0%   0% [kthreadd]
    5     2 root     IW       0   0%   0% [kworker/u2:0-ev]

When host finished capturing (should be idle again):

Mem: 33756K used, 375256K free, 1516K shrd, 1108K buff, 16028K cached
CPU:   9% usr  21% sys   0% nic  68% idle   0% io   0% irq   0% sirq
Load average: 0.55 0.31 0.12 1/43 335
  PID  PPID USER     STAT   VSZ %VSZ %CPU COMMAND
  326   278 root     S     1880   0%  26% /opt/uvc-webcam/uvc-gadget -l -p 21 -b
  334   274 root     R     2756   1%   3% top
    8     2 root     SW       0   0%   0% [ksoftirqd/0]
    1     0 root     S     7564   2%   0% {systemd} /sbin/init
   64     1 root     S     7520   2%   0% /usr/lib/systemd/systemd-udevd
   60     1 root     S     7104   2%   0% /usr/lib/systemd/systemd-journald
   93     1 dbus     S     5008   1%   0% /usr/bin/dbus-daemon --system --addres
   94     1 root     S     2756   1%   0% -sh
  274     1 root     S     2756   1%   0% -sh
  278     1 root     S     2628   1%   0% {start-webcam.sh} /bin/sh /opt/uvc-web
  335     2 root     IW       0   0%   0% [kworker/0:0-eve]
   39     2 root     SW<      0   0%   0% [vchiq-slot/0]
  277     2 root     IW       0   0%   0% [kworker/u2:2-mm]
   42     2 root     IW       0   0%   0% [kworker/0:2-eve]
   14     2 root     SW       0   0%   0% [kcompactd0]
   44     2 root     IW<      0   0%   0% [kworker/0:1H-kb]
  333     2 root     IW       0   0%   0% [kworker/0:1-eve]
   40     2 root     SW<      0   0%   0% [vchiq-recy/0]
    2     0 root     SW       0   0%   0% [kthreadd]
    5     2 root     IW       0   0%   0% [kworker/u2:0-ev]

Expected behavior:
1-5% CPU usage by /opt/uvc-webcam/uvc-gadget -l -p 21 -b on idle after the host system finishes capturing from the v4l2 device.

Additional Notes:
The issue goes away if i restart the RPi, however that is not fitting my use case. In my use case the RPi is plugged in indefinitely into a VR system, wasting more power on idle is the last thing i want.

Host OS: Ubuntu 20.04.3 LTS
Board Running showmewebcam : Raspberry Pi Zero

uname -a from the board: Linux piwebcam 5.10.11 #1 Mon Nov 8 06:25:02 UTC 2021 armv6l GNU/Linux

Would be nice to see some sort of work around/solution to this! If its possible to enforce that state via shell commands that works for me too!

support unicam / libcamera frame sources

Sibling issue to showmewebcam/showmewebcam#186.

Expected Behavior

on systems which use the unicam interface, uvc-gadget should be able to control the filter pipeline

Current Behavior

(not checked, but I'm assuming most V4L controls don't work on the unicam video device, as sensor control is done over libcamera)

Possible Solution

implement a libcamera control mapping backend

Provide a cropping/viewport IPC

What will be a really useful feature for the webcam would be the ability to provide automatic panning/centering to the face. Face recognition is a rather simple task.

My recent poking around shows that access to the camera is not exclusive. Given that is true, we can run a opportunistic face recognition daemon on the pi independent of uvc-gadget and determine the frame that we should crop. Then all we need to do then is a IPC mechanism to communicate between uvc-gadget and the daemon to pan the frame.

Stream flickers

I initially thought this has to do something with the power_line_frequency setting, but it it seems to affect all settings. I've turned down the exposure, to make it more visible:

flicker

Ps. changing the framerate to 1/25 or 1/15 doesn't help

How to use frambuffer devices?

I tried to use frambuffer instead of /dev/video0, but the webcam application show nothing.
Here is what I did:

# ./gadget-framebuffer.sh 
INFO: --- Gadget framebuffer ---
INFO: Framebuffer width:  640
INFO: Framebuffer height: 480
INFO: Configfs path: /sys/kernel/config
INFO: Gadget config path: /sys/kernel/config/usb_gadget/fb_gadget
INFO: Initialize configs and functions
INFO: Enabling gadget
INFO: End

# ./uvc-gadget -u /dev/video1 -f /dev/fb0
[1] 404
root@raspberrypi:/home/pi/tuyenld/uvc-webcam# CONFIGFS: Initial path: /sys/kernel/config/usb_gadget
CONFIGFS: UVC: format: 0, frame: 0, resolution: 640x480, frame_interval: 1000000,  bitrate: [24576000, 49152000]
CONFIGFS: STREAMING maxburst:  0
CONFIGFS: STREAMING maxpacket: 2048
CONFIGFS: STREAMING interval:  1
SETTINGS: Number of buffers requested: 2
SETTINGS: Show FPS: DISABLED
SETTINGS: GPIO pin for streaming status: not set
SETTINGS: Onboard led0 used for streaming status: DISABLED
SETTINGS: Blink on startup: 0 times
SETTINGS: UVC device name: /dev/video1
SETTINGS: FB device name: /dev/fb0
SETTINGS: Framerate for frame buffer: 25
DEVICE_UVC: Opening /dev/video1 device
DEVICE_UVC: Device is 20980000.usb on bus gadget
FB: Opening /dev/fb0 device
FB: Resolution: 640x480
FB: Bits per pixel: 32
FB: Line length: 2560
FB: Memory size: 1228800
UVC: Streaming control: action: INIT
FRAME: format: 0, frame: 0, resolution: 640x480, frame_interval: 1000000,  bitrate: [24576000, 49152000]
DUMP: uvc_streaming_control: format: 0, frame: 0, frame interval: 1000000
UVC: Streaming control: action: INIT
FRAME: format: 0, frame: 0, resolution: 640x480, frame_interval: 1000000,  bitrate: [24576000, 49152000]
DUMP: uvc_streaming_control: format: 0, frame: 0, frame interval: 1000000
PROCESSING LOOP: FB -> UVC
DEVICE_UVC: UVC_EVENT_CONNECT
UVC: INPUT_TERMINAL - GET_INFO - UVC_CT_AE_MODE_CONTROL - DISABLED
UVC: PROCESSING_UNIT - GET_INFO - UVC_PU_BRIGHTNESS_CONTROL - DISABLED
UVC: Streaming request CS: PROBE, REQ: GET_DEF
UVC: Streaming control: action: GET MIN
FRAME: format: 0, frame: 0, resolution: 640x480, frame_interval: 1000000,  bitrate: [24576000, 49152000]
DUMP: uvc_streaming_control: format: 0, frame: 0, frame interval: 1000000
UVC: Streaming request CS: PROBE, REQ: SET_CUR
UVC: Control PROBE, length: 26
UVC: Streaming control: action: SET, format: 0, frame: 0
FRAME: format: 0, frame: 0, resolution: 640x480, frame_interval: 1000000,  bitrate: [24576000, 49152000]
DUMP: uvc_streaming_control: format: 0, frame: 0, frame interval: 1000000
UVC: Streaming request CS: PROBE, REQ: GET_CUR
UVC: PROCESSING_UNIT - GET_DEF - UVC_PU_BRIGHTNESS_CONTROL - DISABLED
UVC: PROCESSING_UNIT - GET_DEF - UVC_PU_BRIGHTNESS_CONTROL - DISABLED
UVC: PROCESSING_UNIT - GET_DEF - UVC_PU_BRIGHTNESS_CONTROL - DISABLED
UVC: PROCESSING_UNIT - GET_DEF - UVC_PU_BRIGHTNESS_CONTROL - DISABLED

I also tried to force HDMI output mode, but no luck.

# cat /boot/config.txt
[...]
hdmi_force_hotplug=1
hdmi_drive=2

Camera preview mode on RasPi is using GPU, so I think it is easy to overlay text or image with Camera video output.
Could you give me more detail how to use framebuffer?

only 24fps achived when stream static vga image

I want benchmark the framerate I can get from usb uvc gadget.
I'm using this on a ultrascale+ mpsoc, which has a 4 core cortex a53, 1.2Ghz cpu.
when stream a static jpg image 640x480 use -i option, the host shows only 24fps,
but the device shows 62 or even 122, when I use -x option to show fps.

Branch feat/new-code

I tried modify

// fb_framerate = 60;
fb_framerate = 120;

in uvc-gadget.c

or even delete the line:

        // nanosleep((const struct timespec[]){{0, 1000000L * (sleep_time - 2)}}, NULL);

in procesing_image_uvc.c

but with no luck.

What's the problem, how can I get more fps?
Thank you!

VS request completed with status -18.

We are using zynq Ultrascale + MPSoC with custom board.
Our board has 2 USB ports(Host 2.0 and device 3.0), 2 SDI(one input and another output).
Kernel version on board is 4.19.0 and In host PC 5.4.0-58-generic.
Final project according to customers requirement is Streaming 1080p video taking input from SDI and taking output from USB UVC(device).
Currently We are trying with connecting C922 Pro Stream Webcam to USB(host) port.This creates /dev/video0 node.
Then modprobe g_webcam. This creates /dev/video1.
Using the application https://github.com/peterbay/uvc-gadget. At host side /dev/video0 is created.
When I try to display using application such as guvcview, at the device side, getting below attached log.
I need some more input so that I can move forward with this project.
From host side:
ffplay /dev/video0
Dequeued v4l2 buffer contains corrupted data (0 bytes).
From device:
[ 1563.216999] VS request completed with status -18.
[ 1563.229986] VS request completed with status -18.
UVC: Possible USB shutdown requested from Host, seen during VIDI[ 1563.234674] VS request completed with status -18.
OC_DQBUF
select timeout
[ 1573.292465] dwc3 fe200000.dwc3: request 00000000af72569b was not queued to ep2in
[ 1573.299868] dwc3 fe200000.dwc3: request 00000000bbc4cf8d was not queued to ep2in
[ 1573.307273] dwc3 fe200000.dwc3: request 00000000849239a7 was not queued to ep2in
[ 1573.314668] dwc3 fe200000.dwc3: request 0000000023561ba0 was not queued to ep2in
UVC: Stopping video stream.
USBGITLOG.txt

Support H264

Would be a great addition and maybe a better performance than MJPEG.

uvc-gadget does not work with Jitsi, Skype and Teams

uvc-gadget does not work by the above mentioned tools. While the webcam is recognized, it only provides a black image. I know that most Jitsi instances filter out all webcams that provide more than 720p, so it's not even possible to select the webcam.

Skype and Teams (at least on Linux) can be forced to recognize the webcam by removing the 1080p resolution from multi-gadget.sh:

config_frame mjpeg m 1920 1080

That works with Jitsi as well. Other tools such as Zoom, guvcview, Cheese etc. have no problems in recognizing the different resolutions:

v4l2-ctl -d /dev/video2 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
	Type: Video Capture

	[0]: 'MJPG' (Motion-JPEG, compressed)
		Size: Discrete 640x360
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
		Size: Discrete 800x600
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
		Size: Discrete 1024x768
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
		Size: Discrete 1280x720
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
		Size: Discrete 1280x960
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
		Size: Discrete 1440x1080
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
		Size: Discrete 1536x864
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
		Size: Discrete 1600x900
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.067s (15.000 fps)
		Size: Discrete 1600x1200
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.040s (25.000 fps)
			Interval: Discrete 0.067s (15.000 fps)

device descriptor error

When you start uvc-gadget, you can find these errors in dmesg:

[ +26,669352] usb 1-6: new high-speed USB device number 76 using xhci_hcd
[  +0,317065] usb 1-6: device descriptor read/64, error -71
[  +6,408941] usb 1-6: device descriptor read/64, error -71
[  +0,222872] usb 1-6: new high-speed USB device number 77 using xhci_hcd
[  +0,137456] usb 1-6: New USB device found, idVendor=1d6b, idProduct=0104, bcdDevice= 1.00
[  +0,000012] usb 1-6: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  +0,000007] usb 1-6: Product: Piwebcam 
[  +0,000007] usb 1-6: Manufacturer: Show-me Webcam Project
[  +0,000006] usb 1-6: SerialNumber: 100000000d2386db
[  +0,044992] uvcvideo: Found UVC 1.00 device Piwebcam  (1d6b:0104)
[  +0,018794] uvcvideo 1-6:2.0: Entity type for entity Processing 2 was not initialized!
[  +0,000012] uvcvideo 1-6:2.0: Entity type for entity Camera 1 was not initialized!
[  +0,000239] input: Piwebcam : UVC Camera as /devices/pci0000:00/0000:00:14.0/usb1/1-6/1-6:2.0/input/input51
[  +0,001267] cdc_acm 1-6:2.2: ttyACM0: USB ACM device

Expose all settings through uvc-gadget

Currently only the following settings are exposed:

$ v4l2-ctl -d /dev/video2 -L
                     brightness 0x00980900 (int)    : min=0 max=100 step=1 default=50 value=50
                  exposure_auto 0x009a0901 (menu)   : min=0 max=3 default=0 value=0
				1: Manual Mode

uvc-gatget don't work on raspberry pi 4 R1.4

I implemented this uvc-gatget on a raspberry pi4 4GB R1.2 and it worked fine. When I tried to run uvc-gadget on raspberry pi4 8GB R1.4 in the same way, the uvc-gadget device disappeared when I accessed the UVC camera from the PC connected via USB. It exists as a device in /dev/ video1 until I access the UVC camera (for example, select the camera in guvcview), but the device disappears as soon as I access it. The following log remains in syslog, but I don't understand what is wrong and it doesn't work as uvc-gadget. How can I get it to work with R1.4 ?

cat /proc/cpuinfo
Hardware: BCM2711
Revision: d03114
Model: Raspberry Pi 4 Model B Rev 1.4

lsb_release -a
Distributor ID : Raspbian
Description : Raspbian GNU/Linux 10 (buster)
Release : 10

syslog
raspberrypi kernel: [ 369.645143] configfs-gadget gadget: uvc: uvc_function_set_alt(1, 1)
raspberrypi kernel: [ 369.645159] configfs-gadget gadget: uvc: reset UVC
raspberrypi kernel: [ 370.263179] configfs-gadget gadget: uvc: VS request completed with status -61.
raspberrypi kernel: [ 370.842185] configfs-gadget gadget: uvc: VS request completed with status -61.
raspberrypi kernel: [ 371.845535] configfs-gadget gadget: uvc: uvc_function_disable()
raspberrypi piwebcam[433]: UVC: Possible USB shutdown requested from Host, seen during VIDIOC_DQBUF
raspberrypi piwebcam[433]: UVC: Possible USB shutdown requested from Host, seen during VIDIOC_DQBUF
raspberrypi piwebcam[433]: PROCESSING: Select timeout
raspberrypi piwebcam[433]: *** UVC GADGET SHUTDOWN ***
raspberrypi piwebcam[433]: DEVICE_V4L2: STREAM OFF success
raspberrypi piwebcam[433]: DEVICE_V4L2: Uninit device
raspberrypi piwebcam[433]: DEVICE_UVC: STREAM OFF success
raspberrypi piwebcam[433]: *** UVC GADGET EXIT ***

Request: Support higher resolution than 1920 x 1080 even if we have to lower frame rate

I would like to use a HQ camera as a document scanner (place a piece of paper under the camera and be able to magnify the output). I know we are limited by bandwidth over USB 2.0 but most USB 2.0 cameras can do higher resolutions that 1080p by sacrificing frame rate for example 2592 (H) x 1944 (V) pixels MJPEG 15fps or even higher if we only want 5fps.

Vertical blank line on the right at 1440x1080

I used Pi Zero + Pi Camera v1.
When I change the setting to 1440x1080 MJPEG, there is a vertical blank pixel on the right.

Picture 2020-11-06 07-54-51

Here is the camera format support list:

# v4l2-ctl --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture

        [0]: 'YU12' (Planar YUV 4:2:0)
                Size: Stepwise 32x32 - 2592x1944 with step 2/2
        [1]: 'YUYV' (YUYV 4:2:2)
                Size: Stepwise 32x32 - 2592x1944 with step 2/2
        [2]: 'RGB3' (24-bit RGB 8-8-8)
                Size: Stepwise 32x32 - 2592x1944 with step 2/2
        [3]: 'JPEG' (JFIF JPEG, compressed)
                Size: Stepwise 32x32 - 2592x1944 with step 2/2
        [4]: 'H264' (H.264, compressed)
                Size: Stepwise 32x32 - 2592x1944 with step 2/2
        [5]: 'MJPG' (Motion-JPEG, compressed)
                Size: Stepwise 32x32 - 2592x1944 with step 2/2
        [6]: 'YVYU' (YVYU 4:2:2)
                Size: Stepwise 32x32 - 2592x1944 with step 2/2
        [7]: 'VYUY' (VYUY 4:2:2)
                Size: Stepwise 32x32 - 2592x1944 with step 2/2
        [8]: 'UYVY' (UYVY 4:2:2)
                Size: Stepwise 32x32 - 2592x1944 with step 2/2
        [9]: 'NV12' (Y/CbCr 4:2:0)
                Size: Stepwise 32x32 - 2592x1944 with step 2/2
        [10]: 'BGR3' (24-bit BGR 8-8-8)
                Size: Stepwise 32x32 - 2592x1944 with step 2/2
        [11]: 'YV12' (Planar YVU 4:2:0)
                Size: Stepwise 32x32 - 2592x1944 with step 2/2
        [12]: 'NV21' (Y/CrCb 4:2:0)
                Size: Stepwise 32x32 - 2592x1944 with step 2/2
        [13]: 'BGR4' (32-bit BGRA/X 8-8-8-8)
                Size: Stepwise 32x32 - 2592x1944 with step 2/2
#

Is 1440x1080 an appropriate resolution?

Thank you for your awesome project.

separate handling of red and blue color balance

(this is an issue submitted by [vogarth] on the showmewebcam Discord)

Expected Behavior

UVC control WHITE_BALANCE_COMPONENT can affect both V4L2_CID_RED_BALANCE and V4L2_CID_BLUE_BALANCE independently.

Current Behavior

(my analysis from reading code, not [vogarth]'s).
V4L2_CID_RED_BALANCE and V4L2_CID_BLUE_BALANCE are both set to the value of V4L2_CID_RED_BALANCE

This affects both master and feat/new-code.

Possible Solution

AFAICS the UVC control sends two bytes (red/blue separately) as control value, and v4l2_set_ctrl only receives a single int, which it sets for both channels. There should probably be some additional handling for handling multi-byte UVC controls.

How to disable auto exposure and set manual exposure time?

I follows your guide and enable raspberrypi camera_v2 as a USB Camera for Windows PC.
The bmControls changed as follows:
cat /sys/kernel/config/usb_gadget/pi4/functions/uvc.usb0/control/processing/default/bmControls
255
47

cat /sys/kernel/config/usb_gadget/pi4/functions/uvc.usb0/control/terminal/camera/default/bmControls
14
0
0

Now the brightness/saturation/sharpness/contrast can runtime change and take effect, but the auto exposure mode is always 0 and change the exposure time don't take effect.
I also change the /usr/bin/v4l2-ctl -c auto_exposure=1, then the auto exposure mode is fixed to manual mode, the exposure time can runtime change and take effect, but the auto exposure mode can't change to auto mode any more.
It looks like the auto exposure mode is fixed by below codes and can be changed. If delete the line /usr/bin/v4l2-ctl -c auto_exposure=0, the result is the auto exposure mode is fixed to auto mode.

#!/bin/bash

sudo /home/pi/uvc-gadget/multi-gadget.sh
/usr/bin/v4l2-ctl -c auto_exposure=0 // change to 1 manual mode
/usr/bin/v4l2-ctl -c auto_exposure_bias=8
/usr/bin/v4l2-ctl -c contrast=20
/usr/bin/v4l2-ctl -c video_bitrate=25000000
sudo /home/pi/uvc-gadget/uvc-gadget -u /dev/video1 -v /dev/video0

The test application as follows, the Auto Exposure Mode is always 0 even if I call cap.set(CV_CAP_PROP_AUTO_EXPOSURE, 1) to change to manual AE mode. The application can work well is use Windows PC default front camera.

#include "opencv2/opencv.hpp"
#include

using namespace cv;
using namespace std;

int main()
{
VideoCapture cap(1);
Mat frame;

auto exp_time = cap.get(CV_CAP_PROP_EXPOSURE);
cout << "Init Exposure Time: " << exp_time << endl;

auto gain = cap.get(CV_CAP_PROP_GAIN);
cout << "Init Gain: " << gain << endl;

auto ae_mode = cap.get(CV_CAP_PROP_AUTO_EXPOSURE);
cout << "Init Auto Exposure Mode: " << ae_mode << endl << endl;

cap.set(CV_CAP_PROP_AUTO_EXPOSURE, 1);

exp_time = cap.get(CV_CAP_PROP_EXPOSURE);
cout << "Exposure Time: " << exp_time << endl;

gain = cap.get(CV_CAP_PROP_GAIN);
cout << "Gain: " << gain << endl;

ae_mode = cap.get(CV_CAP_PROP_AUTO_EXPOSURE);
cout << "Auto Exposure Mode: " << ae_mode << endl << endl;

cap >> frame;

int i = 0;
while (waitKey(30) != 27)
{
	i++;
	i %= 100;
	cap.set(CV_CAP_PROP_EXPOSURE, (i / 10) - 10);

	exp_time = cap.get(CV_CAP_PROP_EXPOSURE);
	cout << "Exposure Time:" << exp_time << endl;

	gain = cap.get(CV_CAP_PROP_GAIN);
	cout << "Gain: " << gain << endl;

	ae_mode = cap.get(CV_CAP_PROP_AUTO_EXPOSURE);
	cout << "Auto Exposure Mode: " << ae_mode << endl << endl;

	cap >> frame;
	putText(frame, "Exposure:" + to_string(i / 10 - 10), Point(20, 30), 3, 1.0, Scalar(255, 0, 0));
	imshow("Piwebcam", frame);
}

return 0;

}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.