UVC Module API Manual#
Overview#
The UVC module is used to access USB cameras in CanMV Python.
The module uses FOURCC to describe video formats. The supported host input formats are:
UVC.FOURCC_YUY2UVC.FOURCC_UYVYUVC.FOURCC_NV12UVC.FOURCC_I420UVC.FOURCC_MJPEG
Only a single UVC camera is supported by default.
Recommended Workflow#
UVC.probe()to detect the cameraUVC.list_video_mode()to view the modes supported by the deviceUVC.video_mode(...)to construct the target modeUVC.select_video_mode(...)to select and negotiate the modeUVC.start(...)to start the video streamLoop calling
UVC.snapshot()to get imagesUVC.stop()to stop the video stream
It is recommended to call UVC.stop() inside a try/finally block to ensure proper stream shutdown even on abnormal exit.
API Reference#
UVC.probe() - Detect Camera#
Function
Detects whether a UVC camera is currently connected to the system, and returns the vendor/product string.
Syntax
from media.uvc import UVC
plugin, devname = UVC.probe()
Return Values
Return Value |
Type |
Description |
|---|---|---|
|
|
Whether a UVC camera is detected |
|
|
Device information, in the format |
Example
plugin, devinfo = UVC.probe()
print(f"detect: {plugin}, devinfo: {devinfo}")
UVC.video_mode() - Get or Construct Video Mode#
Function
When called without arguments: returns the currently negotiated video mode
When called with arguments: constructs a target video mode object
Syntax
# Get current mode
mode = UVC.video_mode()
# Construct target mode
mode = UVC.video_mode(width, height, fourcc, fps)
Parameters
Parameter |
Type |
Description |
|---|---|---|
|
|
Image width |
|
|
Image height |
|
|
Pixel format, uses |
|
|
Target frame rate |
Description
When
fourccis omitted,UVC.FOURCC_MJPEGis used by defaultWhen
fpsis omitted,frameinterval = 0is passed to the lower layer, allowing the driver to select the default frame rateAfter
UVC.select_video_mode()succeeds, the returned mode object will be updated to the actual negotiated values
UVC.list_video_mode() - List Device Supported Modes#
Function
Enumerates the full list of modes supported by the camera. Each item in the list is a uvc_video_mode object containing width, height, fourcc, and fps.
Syntax
modes = UVC.list_video_mode()
Example
for i, mode in enumerate(UVC.list_video_mode()):
print(f"{i}: {mode}")
UVC.select_video_mode(mode) - Select Video Mode#
Function
Initializes the UVC device according to the user-specified target mode, and returns the actual negotiated mode.
Syntax
succ, actual_mode = UVC.select_video_mode(mode)
Parameters
Parameter |
Type |
Description |
|---|---|---|
|
|
Target mode |
Return Values
Return Value |
Type |
Description |
|---|---|---|
|
|
Whether initialization succeeded |
|
|
The actual negotiated mode |
Common FOURCC
The mode.fourcc passed into UVC.select_video_mode() typically uses the following constants:
Constant |
Description |
|---|---|
|
YUY2 / YUYV 4:2:2 |
|
UYVY 4:2:2 |
|
NV12 4:2:0 |
|
I420 4:2:0 |
|
MJPEG compressed format |
UVC.start() - Start Video Stream#
Function
Starts the UVC video stream and configures the return type of snapshot().
Syntax
success = UVC.start(delay_ms=0, cvt=True)
Parameters
Parameter |
Type |
Description |
|---|---|---|
|
|
Additional wait time in milliseconds after starting |
|
|
Whether to perform format conversion on |
cvt Semantics
Input Format |
|
|
|---|---|---|
|
|
Returns JPEG image |
|
Returns RGB565 image |
Returns YUV422 image |
|
Returns RGB565 image |
Returns YUV422 image |
|
Not supported, will raise exception in |
Returns YUV420 image |
|
Not supported, will raise exception in |
Returns YUV420 image |
UVC.stop() - Stop Video Stream#
Function
Stops the UVC video stream and releases internal state.
Syntax
UVC.stop()
UVC.snapshot() - Get One Frame Image#
Function
Takes one frame image from the current video stream.
Syntax
frame = UVC.snapshot()
frame = UVC.snapshot(timeout_ms)
Parameters
Parameter |
Type |
Description |
|---|---|---|
|
|
Timeout for getting one frame, in milliseconds |
Return Value
The return type depends on the current fourcc and UVC.start(cvt=...) configuration:
Current Mode |
Returned Object |
|---|---|
|
NV12 video frame object |
|
JPEG |
|
RGB565 |
|
YUV422 |
|
YUV420 |
Description
May return
Noneon timeout or when no new frame is temporarily availableNV12/I420will raise aRuntimeErrorwhencvt=True
uvc_video_mode Object#
Fields#
Field |
Type |
Description |
|---|---|---|
|
|
Width |
|
|
Height |
|
|
Pixel format |
|
|
Current mode frame rate |
Print Example#
mode = UVC.video_mode(640, 480, UVC.FOURCC_MJPEG, 30)
print(mode)
Output example:
{"width":640, "height":480, "format":mjpeg, "fourcc":0x47504a4d, "fps":30.00}
Note:
formatis only reflected in the print stringThe field actually used in code to determine the format is
mode.fourcc
Example#
Example 1: MJPEG Software Decode Display#
Corresponding project example: src/canmv/resources/examples/02-Media/uvc.py
import time, gc
from media.display import *
from media.uvc import *
DISPLAY_WIDTH = ALIGN_UP(800, 16)
DISPLAY_HEIGHT = 480
Display.init(Display.ST7701, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, to_ide=True)
while True:
plugin, dev = UVC.probe()
if plugin:
print(f"detect USB Camera {dev}")
break
mode = UVC.video_mode(640, 480, UVC.FOURCC_MJPEG, 30)
succ, mode = UVC.select_video_mode(mode)
print(f"select mode success: {succ}, mode: {mode}")
UVC.start(cvt=False)
clock = time.clock()
try:
while True:
clock.tick()
img = UVC.snapshot()
if img is not None:
img = img.to_rgb565()
Display.show_image(img)
img.__del__()
gc.collect()
print(f"fps: {clock.fps()}")
finally:
UVC.stop()
time.sleep_ms(100)
Display.deinit()
Example 2: MJPEG Hardware Decode then CSC#
Corresponding project example: src/canmv/resources/examples/02-Media/uvc_with_csc.py
import time, gc
from media.display import *
from media.uvc import *
from nonai2d import CSC
DISPLAY_WIDTH = ALIGN_UP(800, 16)
DISPLAY_HEIGHT = 480
csc = CSC(CSC.PIXEL_FORMAT_RGB_565)
Display.init(Display.ST7701, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, to_ide=True)
while True:
plugin, dev = UVC.probe()
if plugin:
print(f"detect USB Camera {dev}")
break
time.sleep_ms(100)
mode = UVC.video_mode(640, 480, UVC.FOURCC_MJPEG, 30)
succ, mode = UVC.select_video_mode(mode)
print(f"select mode success: {succ}, mode: {mode}")
UVC.start(cvt=True)
clock = time.clock()
try:
while True:
clock.tick()
img = UVC.snapshot()
if img is None:
continue
img = csc.convert(img)
Display.show_image(img)
img.__del__()
gc.collect()
print(f"fps: {clock.fps()}")
finally:
UVC.stop()
time.sleep_ms(100)
csc.destroy()
Display.deinit()
Example 3: YUY2 Directly Convert to RGB565 Display#
import time, gc
from media.display import *
from media.uvc import *
DISPLAY_WIDTH = ALIGN_UP(800, 16)
DISPLAY_HEIGHT = 480
Display.init(Display.ST7701, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, to_ide=True)
while True:
plugin, dev = UVC.probe()
if plugin:
print(f"detect USB Camera {dev}")
break
time.sleep_ms(100)
mode = UVC.video_mode(640, 480, UVC.FOURCC_YUY2, 30)
succ, mode = UVC.select_video_mode(mode)
print(f"select mode success: {succ}, mode: {mode}")
UVC.start(cvt=True)
clock = time.clock()
try:
while True:
clock.tick()
img = UVC.snapshot()
if img is None:
continue
Display.show_image(img)
img.__del__()
gc.collect()
print(f"fps: {clock.fps()}")
finally:
UVC.stop()
time.sleep_ms(100)
Display.deinit()
Notes#
UVC.stop()is recommended to always be called infinally.UVC.start(cvt=True)only affects the content returned bysnapshot(); it does not change thefourccactually negotiated on the USB side.NV12/I420currently do not support direct conversion insnapshot(cvt=True).It is not recommended to connect UVC cameras and devices that heavily occupy USB bandwidth through a Hub at the same time.
