v4l2_drm Python Usage Reference#
Overview#
k230_v4l2_drm is a Python binding library for V4L2 video capture and DRM display on the Kendryte K230 platform. It integrates Linux V4L2 (Video4Linux2) camera capture and DRM (Direct Rendering Manager) display output into a unified pipeline, supporting:
Multi-channel camera capture: capture multiple video streams simultaneously through multiple contexts
Zero-copy DRM display: V4L2 buffers are sent directly to DRM display without additional copying
OSD overlay: overlay ARGB8888/RGB888 layers (such as detection boxes, text) on video frames
Rotation/flip: hardware-level rotation (0°/90°/180°/270°) and mirror flip
Cropping/offset: set display offset and crop area
Background display thread:
display_start()continuously refreshes the display in a background thread
Reference examples: py_demo/ai/yolo_v4l2_drm.py, Face Detection py_demo/ai/face_detect.py
Quick Start#
Example 1: Camera Direct Display#
The simplest mode: camera capture → DRM display, without AI inference.
import time
from k230_v4l2_drm import V4l2Drm, ROTATION_0, ROTATION_90
v4l2 = V4l2Drm(context_num=1)
display_width, display_height = v4l2.drm_init()
print(f"INFO: display {display_width}x{display_height}")
# Automatically select rotation angle based on display orientation
if display_width > display_height:
rotation = ROTATION_0
else:
rotation = ROTATION_90
v4l2.set_context(
index=0, device=1,
width=max(display_width, display_height), height=min(display_width, display_height),
format="NV12", display=True
)
v4l2.set_rotation(0, rotation)
if not v4l2.setup():
print("Error: V4L2-DRM setup failed!")
exit(-1)
v4l2.display_start()
try:
while True:
time.sleep(1) # After display_start, the background thread handles capture and display automatically; the main thread sleeps and waits
except KeyboardInterrupt:
print("\nStopping...")
v4l2.display_stop()
print("Done!")
Example 2: AI Inference + OSD Overlay Display#
Dual contexts: one for display, one for AI inference, with OSD overlay of detection results.
import time
import numpy as np
import cv2
from k230_v4l2_drm import V4l2Drm, DRM_FORMAT_ARGB8888, ROTATION_0, ROTATION_90
# Create dual-instance, enable OSD
v4l2 = V4l2Drm(context_num=2, osd=True)
display_w, display_h = v4l2.drm_init()
print(f"INFO: display {display_w}x{display_h}")
# Automatically select rotation angle based on display orientation
if display_w > display_h:
rotation = ROTATION_0
else:
rotation = ROTATION_90
# Context 0: Camera 1 → Display (NV12)
v4l2.set_context(
index=0, device=1,
width=max(display_w, display_h), height=min(display_w, display_h),
format="NV12", display=True
)
# Context 1: Camera 2 → AI inference input (BG3P format, no display)
v4l2.set_context(
index=1, device=2,
width=1280, height=720,
format="BG3P", display=False
)
v4l2.set_rotation(0, rotation)
# Configure OSD format
v4l2.set_osd_format(DRM_FORMAT_ARGB8888)
# Initialize pipeline
if not v4l2.setup():
print("Error: V4L2-DRM setup failed!")
exit(-1)
v4l2.display_start()
v4l2.dump_start(index=1) # Start AI channel capture
try:
frame_count = 0
fps = 0.0
fps_start_time = time.time()
while True:
# Capture AI channel frame
if not v4l2.dump_frame(index=1, timeout_ms=1000):
continue
# Get frame data (BG3P format: shape=(3, H, W))
frame = v4l2.get_buffer_array(index=1)
# Release frame buffer
v4l2.dump_release(index=1)
# AI inference (using nncaseruntime, etc.)
# results = ai_inference(frame)
# Frame rate statistics
frame_count += 1
elapsed = time.time() - fps_start_time
if elapsed >= 1.0:
fps = frame_count / elapsed
frame_count = 0
fps_start_time = time.time()
print(f"[{time.strftime('%H:%M:%S')}] FPS: {fps:.1f}")
# Generate OSD image (ARGB8888)
osd_img = np.zeros((min(display_w, display_h), max(display_w, display_h), 4), dtype=np.uint8)
# Draw detection boxes, text, etc. on osd_img...
# cv2.rectangle(osd_img, (x1, y1), (x2, y2), (B, G, R, A), 2)
# Display FPS on OSD
cv2.putText(osd_img, f"FPS: {fps:.1f}", (10, 40),
cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 255, 0, 255), 2)
# Update OSD display
v4l2.osd_update(osd_img)
except KeyboardInterrupt:
print("\nStopping...")
v4l2.dump_stop(index=1)
v4l2.display_stop()
print("Done!")
