DRM/KMS Preview
Relevant source files
The following files were used as context for generating this wiki page: - [picamera2/previews/drm_preview.py](https://github.com/przkos/picamera2/blob/HEAD/picamera2/previews/drm_preview.py) - [picamera2/picamera2.py](https://github.com/przkos/picamera2/blob/HEAD/picamera2/picamera2.py) - [picamera2/previews/null_preview.py](https://github.com/przkos/picamera2/blob/HEAD/picamera2/previews/null_preview.py) - [picamera2/previews/__init__.py](https://github.com/przkos/picamera2/blob/HEAD/picamera2/previews/__init__.py) - [CHANGELOG.md](https://github.com/przkos/picamera2/blob/HEAD/CHANGELOG.md) - [tests/test_list_drm.txt](https://github.com/przkos/picamera2/blob/HEAD/tests/test_list_drm.txt) - [examples/imx500/imx500_segmentation_demo.py](https://github.com/przkos/picamera2/blob/HEAD/examples/imx500/imx500_segmentation_demo.py)The DRM/KMS preview is a backend for rendering camera frames directly to a display without requiring a windowing system like X11. It utilizes the Linux Direct Rendering Manager (DRM) and Kernel Mode Setting (KMS) APIs, making it ideal for embedded applications or for use on headless systems like the Raspberry Pi OS Lite. This preview backend is implemented in the DrmPreview class.
The picamera2 library can automatically select the DrmPreview backend when no DISPLAY environment variable is detected, or it can be explicitly requested. It supports features like image transformations (flips), aspect ratio preservation, and displaying RGBA overlays on top of the camera feed.
Sources: picamera2/previews/drm_preview.py, picamera2/picamera2.py:657-664
Architecture and Core Components
The DRM preview functionality is primarily managed by two classes: DrmManager and DrmPreview. DrmPreview inherits its basic event loop structure from NullPreview.
Sources: picamera2/previews/drm_preview.py, picamera2/previews/null_preview.py
Class Diagram
This diagram shows the relationship between the main classes involved in the DRM preview system.
DrmManager
The DrmManager class acts as a singleton to manage shared DRM resources. It ensures that DRM hardware (graphics card, display controller) is initialized only once and is shared among any DrmPreview instances.
- Resource Management: It handles the reservation of the DRM card, resource manager (
resman), a connector, and a CRTC (CRT Controller) upon first use. - Reference Counting: A
use_counttracks the number of activeDrmPreviewinstances. DRM resources are allocated when the count goes from 0 to 1 and released when it returns to 0. - Thread Safety: A
threading.Lockprotects access to shared resources and the use count.
Sources: picamera2/previews/drm_preview.py:15-46
DrmPreview
This class represents a single preview window on the screen. It inherits from NullPreview and overrides methods to perform rendering via DRM.
- Initialization: When a
DrmPreviewis created, it registers with theDrmManagerto acquire necessary DRM resources. It also defines the window position and size. - Rendering: The
render_requestmethod is called for each new frame. It, in turn, callsrender_drmwhich handles the low-level details of creating DRM framebuffers and scheduling an atomic commit to display the image. - Overlays: Provides a
set_overlaymethod to display a semi-transparent RGBA image on top of the camera feed. - Format Support: A format map (
FMT_MAP) translatespicamera2pixel format strings topykmspixel formats.
Sources: picamera2/previews/drm_preview.py:48-316
Initialization and Lifecycle
The lifecycle of a DrmPreview is tied to the start_preview and stop_preview calls in the main Picamera2 class.
The following sequence diagram illustrates the creation and startup process of a DrmPreview.
When stop() is called on the DrmPreview instance, it signals the DrmManager to decrement its use_count. If the count reaches zero, all DRM resources are released.
Sources: picamera2/previews/drm_preview.py:304-316, 33-46
Frame Rendering Process
Frame rendering is driven by an event loop that processes completed camera requests. The render_drm method contains the core logic for displaying a frame buffer on the screen.
This flowchart outlines the steps taken within render_drm for each frame.
Key aspects of the rendering process include:
- Atomic Commits: It uses
pykms.AtomicReqto ensure that the main image plane and the overlay plane are updated simultaneously, preventing tearing or flickering. - Letterboxing: To preserve the aspect ratio of the camera image, the code calculates a "letterbox" or "pillarbox" view, centering the image within the specified window dimensions.
- Framebuffer Caching:
DmabufFramebufferobjects, which wrap the camera's DMA buffers for DRM, are cached in a dictionary (self.drmfbs) to avoid recreating them for every frame. This cache is cleared when the camera is stopped and restarted. - MJPEG Decoding: If the stream format is MJPEG, the frame is first decoded into an RGB buffer before being displayed. A dedicated framebuffer is allocated for this purpose.
Sources: picamera2/previews/drm_preview.py:186-193, 230-264, 281, 80-92
Key Features
Supported Pixel Formats
The DrmPreview supports a specific set of pixel formats. It maps the picamera2 format string to a pykms.PixelFormat enum.
| Picamera2 Format | pykms.PixelFormat |
|---|---|
RGB888 | RGB888 |
BGR888 | BGR888 |
XRGB8888 | XRGB8888 |
XBGR8888 | XBGR8888 |
YUV420 | YUV420 |
YVU420 | YVU420 |
MJPEG | BGR888 (decoded to) |
Note: The changelog indicates that support was improved for DRM displays where "XB24" is not available, with a fallback to "XR24". This is handled during the MJPEG buffer allocation.
Sources: picamera2/previews/drm_preview.py:51-61, 80-87, CHANGELOG.md:41
Overlays
The DrmPreview can display a semi-transparent overlay on top of the video feed.
- Usage: Call
picam2.set_overlay(overlay_array). - Format: The overlay must be a 4-channel NumPy array (Height, Width, RGBA).
- Implementation: The
set_overlaymethod creates apykms.DumbFramebufferand writes the NumPy array data into it. Therender_drmmethod then adds this framebuffer to a separate overlay plane in the atomic request. - Requirement: To use overlays, the camera configuration must have
buffer_countset to 2 or more.
Sources: picamera2/previews/drm_preview.py:133-163, examples/imx500/imx500_segmentation_demo.py:60
Transformations
Horizontal and vertical flipping of the preview image is supported.
- Configuration: A
libcamera.Transformobject withhfliporvflipset toTrueis passed to theDrmPreviewconstructor. - Implementation: The transform is applied by setting the DRM plane's
rotationproperty. This is a hardware-accelerated operation and is very efficient.
Sources: picamera2/previews/drm_preview.py:114, 206-213
Configuration and Usage
To use the DRM preview, pass Preview.DRM to the start_preview method.
from picamera2 import Picamera2, Preview
import time
picam2 = Picamera2()
# Start a preview at 100,100 with size 800x600
picam2.start_preview(Preview.DRM, x=100, y=100, width=800, height=600)
# The camera is now running and displaying a preview
time.sleep(5)
picam2.stop_preview()
Sources: picamera2/picamera2.py:646, tests/test_list_drm.txt
DrmPreview Constructor Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
x | int | 0 | X-coordinate of the preview window's top-left corner. |
y | int | 0 | Y-coordinate of the preview window's top-left corner. |
width | int | 640 | Width of the preview window. |
height | int | 480 | Height of the preview window. |
transform | libcamera.Transform | None | Image transformation (e.g., hflip, vflip). |
Sources: picamera2/previews/drm_preview.py:63-64
Summary
The DRM/KMS preview system provides an efficient, low-overhead method for displaying camera output directly on a connected screen. By leveraging kernel-level APIs, it bypasses the need for a full desktop environment, making it a powerful tool for embedded vision projects and applications running on minimal OS installations. Its support for hardware-accelerated transformations and overlays further enhances its utility.