v4l2_drm Python使用参考#
概述#
k230_v4l2_drm 是嘉楠堪智 K230 平台上 V4L2 视频采集与 DRM 显示的 Python 绑定库。它将 Linux V4L2 (Video4Linux2) 摄像头采集和 DRM (Direct Rendering Manager) 显示输出整合为统一的流水线,支持:
多路摄像头采集:通过多个 context 同时采集多路视频
零拷贝 DRM 显示:V4L2 buffer 直接送 DRM 显示,无需额外拷贝
OSD 叠加:在视频画面上叠加 ARGB8888/RGB888 图层(如检测框、文字)
旋转/翻转:硬件级旋转 (0°/90°/180°/270°) 和镜像翻转
裁剪/偏移:设置显示偏移和裁剪区域
后台显示线程:
display_start()在后台线程持续刷新显示
快速开始#
示例1:摄像头直出显示#
最简单的模式:摄像头采集 → DRM 显示,无 AI 推理。
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}")
# 根据显示方向自动选择旋转角度
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) # display_start 后台线程自动处理采集和显示,主线程休眠等待
except KeyboardInterrupt:
print("\nStopping...")
v4l2.display_stop()
print("Done!")
示例2:AI 推理 + OSD 叠加显示#
双路 context:一路显示,一路 AI 推理,OSD 叠加检测结果。
import time
import numpy as np
import cv2
from k230_v4l2_drm import V4l2Drm, DRM_FORMAT_ARGB8888, ROTATION_0, ROTATION_90
# 创建双路实例, 启用OSD
v4l2 = V4l2Drm(context_num=2, osd=True)
display_w, display_h = v4l2.drm_init()
print(f"INFO: display {display_w}x{display_h}")
# 根据显示方向自动选择旋转角度
if display_w > display_h:
rotation = ROTATION_0
else:
rotation = ROTATION_90
# Context 0: 摄像头1 → 显示 (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: 摄像头2 → AI推理输入 (BG3P格式, 不显示)
v4l2.set_context(
index=1, device=2,
width=1280, height=720,
format="BG3P", display=False
)
v4l2.set_rotation(0, rotation)
# 配置OSD格式
v4l2.set_osd_format(DRM_FORMAT_ARGB8888)
# 初始化流水线
if not v4l2.setup():
print("Error: V4L2-DRM setup failed!")
exit(-1)
v4l2.display_start()
v4l2.dump_start(index=1) # 启动AI路采集
try:
frame_count = 0
fps = 0.0
fps_start_time = time.time()
while True:
# 采集AI路帧
if not v4l2.dump_frame(index=1, timeout_ms=1000):
continue
# 获取帧数据 (BG3P格式: shape=(3, H, W))
frame = v4l2.get_buffer_array(index=1)
# 释放帧缓冲区
v4l2.dump_release(index=1)
# AI推理 (使用nncaseruntime等)
# results = ai_inference(frame)
# 帧率统计
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}")
# 生成OSD图像 (ARGB8888)
osd_img = np.zeros((min(display_w, display_h), max(display_w, display_h), 4), dtype=np.uint8)
# 在osd_img上绘制检测框、文字等...
# cv2.rectangle(osd_img, (x1, y1), (x2, y2), (B, G, R, A), 2)
# 显示帧率到OSD
cv2.putText(osd_img, f"FPS: {fps:.1f}", (10, 40),
cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 255, 0, 255), 2)
# 更新OSD显示
v4l2.osd_update(osd_img)
except KeyboardInterrupt:
print("\nStopping...")
v4l2.dump_stop(index=1)
v4l2.display_stop()
print("Done!")
