3.21. sample_lvgl_camera Usage Guide

3.21.1. Overview

sample_lvgl_camera is an LVGL-based camera UI sample. On a MIPI panel in the quick-start environment, it demonstrates a full application path: live preview, touch interaction, capture / record, and gallery playback (video has no audio).

Features:

  • Live preview: Camera Sensor output goes through VIN ISP VSE as NV12 and is shown full-screen on a DRM video plane.

  • Touch UI: LVGL draws semi-transparent widgets on a DRM ARGB overlay plane. Touch uses Linux evdev (not LVGL’s built-in LV_USE_EVDEV).

  • Capture: Asynchronous JPEG still capture with timestamp watermark and shutter feedback.

  • Record: Hardware H.264 encode, muxed to MP4; gallery list supports browse / delete.

  • Gallery playback: Stills are hardware-decoded JPEG and shown full-screen on the UI layer by default; tapping a video demuxes with FFmpeg, then VPU hardware-decodes H.264 onto the video plane.

  • Status: Remaining shot estimate and free storage; when space is low, shows FULL, refuses saves, and may auto-stop recording.

Note: This sample targets a specific product setup (720×1280 portrait MIPI LCD + 720×1280 touch panel + SC230AI).

3.21.1.1. Software Architecture

Software layers (top to bottom):

software_architecture_diagram

  • Application UI: ui_camera / ui_gallery — camera main UI, status bar, shutter / REC / gallery controls.

  • LVGL framework: LVGL 9.x widgets, timers, and event loop; flush and input go through the port layer.

  • Display / input port: lvgl_display (ARGB8888 → DRM overlay), lvgl_input (evdev touch).

  • Camera business logic: camera_pipeline — preview thread, JPEG capture, H.264 record and remux, still / video playback.

  • Multimedia and display: VIN / ISP / VSE, encoder, vp_display video plane, drm_ui_plane UI overlay.

  • System status: sys_status reads battery (/sys/class/power_supply; show if present, hide if not) and free storage for the status bar and storage-guard logic.

Dual-plane display:

Layer Typical plane Format Content
Video 33 NV12 Camera preview; gallery video / stills
UI Runtime-scanned ARGB overlay (e.g. 40) ARGB8888 LVGL viewfinder UI (cream frame / bottom bar + controls, with alpha blend)

3.21.1.2. Code Location and Directory Structure

  • Location: app/samples/platform_samples/sample_lvgl_camera

  • Layout:

sample_lvgl_camera/
├── Makefile
├── README.md
├── setup_lvgl.sh                      # Fetch LVGL 9.5.0 → third_party/lvgl
├── config/
│   └── lv_conf.h                      # LVGL build-time config (color depth, features, etc.)
├── src/
│   ├── main.c                         # Entry, args, main loop
│   ├── camera/
│   │   ├── camera_pipeline.c/.h       # VIN→ISP→VSE preview + capture/record
│   │   ├── media_still.c/.h           # JPEG / watermark / sidecars
│   │   ├── media_player.c/.h          # Gallery MP4 hardware decode playback
│   │   └── rec_mux.c/.h               # Annex-B H.264 → MP4
│   ├── drm/
│   │   ├── drm_ui_plane.c/.h          # UI ARGB overlay
│   │   ├── vp_display.c/.h            # Video DRM plane (with overlay)
│   │   └── uthash.h                   # Used by vp_display
│   ├── lvgl_port/
│   │   ├── lvgl_display.c/.h          # LVGL → DRM ARGB flush
│   │   └── lvgl_input.c/.h            # Linux evdev + board calibration
│   ├── system/
│   │   └── sys_status.c/.h            # Poll battery, temperature, and storage; UI shows free space (FULL / xxMB / xxGB), and battery % when capacity is available.
│   │
│   │
│   └── ui/
│       ├── ui_camera.c/.h             # Camera UI + shutter feedback
│       └── ui_gallery.c/.h            # Gallery
└── third_party/lvgl/                  # LVGL sources (created by setup_lvgl.sh)

The build also links sibling trees:

  • platform_samples/utils/*.c

  • platform_samples/vp_sensors/** (sensor config tables)

3.21.1.3. API Flow Description

api_flow_diagram

Typical startup:

  1. apply_product_env_defaults(): apply default environment variables (rotation, frame, touch offset, etc.).

  2. Parse -s / -c / -i.

  3. camera_pipeline_init(): create sensor path, start VSE drain thread, init MIPI DRM video plane.

  4. drm_ui_plane_init() + lvgl_display_init(): create UI overlay and LVGL display.

  5. lvgl_input_init(): open touch device and register pointer indev (warn only on failure; can run without touch).

  6. ui_camera_create(): create camera UI and bind capture / record / gallery callbacks.

  7. camera_pipeline_start_preview(): commit video + UI together.

  8. Main loop: lv_timer_handler() + DRM UI flip; on SIGINT / SIGTERM, stop recording and release resources.

3.21.2. Environment Preparation

  • SC230AI module, correctly connected to MIPI CSI

  • MIPI LCD (product defaults tuned for 720×1280 portrait)

  • Touch driver loaded; /dev/input/event* present (product uses gt9xx, for example, loading the driver with modprobe gt9xx_core)

  • DRM display path available (/dev/dri nodes present)

3.21.3. Build and Deploy

3.21.3.1. Build

This sample builds as part of the SDK and needs headers/libs such as those under out/deploy/system.

Build options:

  • Full / recommended build:

# From the SDK root, perform a complete build.
./bd.sh

# Or build platform_samples (includes sample_lvgl_camera) from the SDK root.
./bd.sh app
  • This directory only:

cd app/samples/platform_samples/sample_lvgl_camera
make
# Output: ./lvgl_camera

3.21.3.2. Deploy

After build and install, the binary is typically on the board at:

  • /app/platform_samples/sample_lvgl_camera/lvgl_camera

You may also copy lvgl_camera to the board (e.g. /userdata) and make it executable:

chmod +x lvgl_camera

3.21.4. Running

3.21.4.1. How to Run

On the board:

cd /app/platform_samples/sample_lvgl_camera
./lvgl_camera

3.21.4.2. UI Controls

Figure 1 — Preview (viewfinder)

Preview

Live preview sits in the cream-colored frame. The bottom bar, left to right: Album, Shutter (large black circle), REC (small red circle). Tap shutter to save a JPEG; tap REC to start / stop recording.

Figure 2 — Gallery

Gallery

Recent photos and videos are listed newest first. Tap an item to view a still or play an MP4 (no audio). Del removes the item; Close returns to the preview.

Control Action Output
Shutter (large black circle, center of bottom bar) JPEG capture (timestamp watermark) + shutter feedback /userdata/lvgl_camera/capture_*.jpg
REC (small red circle next to shutter) Start / stop recording /userdata/lvgl_camera/record_*.mp4 and sidecars
Gallery List, delete, view stills, play video

Sidecar files next to each recording (same basename):

File Purpose
.mp4 Video file
.poster.jpg First-frame poster for list / pre-roll
.a565 Short looping list thumb (~first 3 s, 5 fps, 160×90 RGB565)
.vdur Duration in seconds (text) for list / progress

Deleting a media item also removes these sidecars. .poster.jpg is not listed as a standalone album entry. Photo list thumbs decode JPEG on the fly by default.

3.21.4.3. Expected Behavior

When running successfully:

  • MIPI panel shows dual planes — live preview underneath; cream frame / bottom bar UI on top (gallery / shutter / REC).

  • Tap Capture to write JPEG; tap REC to start, tap again to stop and write MP4.

  • Open the gallery to browse recent media; tap a video for hardware-decoded playback (no audio).

  • Serial logs similar to: Camera pipeline ready (1920x1080 -> MIPI plane 33), sample_lvgl_camera running, lvgl_input: touch ready ....

Clean exit: send Ctrl+C on the serial console; the app stops recording and releases DRM / LVGL resources.