velxio/test/test-esp32-cam/autosearch/01_state_of_the_art.md

5.0 KiB
Raw Blame History

01 — state of the art

What other projects have done about emulating the OV2640 / ESP32-CAM camera, with an honest "does it apply to Velxio?" verdict for each.

Espressif official QEMU fork

Camera support: none. The peripheral list in the docs covers UART, GPIO, SPI, I²C, RMT, LEDC, Wi-Fi (rudimentary), Ethernet — no DVP, no I²S parallel-input mode, no OV2640 device. There is a "virtual RGB panel" that the firmware can write to, but there is no way for the firmware to read frames in.

Verdict: doesn't help. Even Espressif's own QEMU has no camera input.

lcgamboa QEMU fork (the one we ship)

The README brags about three additions over Espressif's fork: dynamic library compilation, Wi-Fi+ESP-NOW, and IOMUX. No camera. A grep over hw/ confirms zero references to ov2640, dvp, i2s_cam, or camera. See 02_qemu_lcgamboa_audit.md for the per-file inventory.

Verdict: doesn't help either. Forking is feasible but a multi-week effort (see Path B in 00_overview.md).

Wokwi (commercial competitor)

Sample projects exist under wokwi.com slugs that render an ESP32-CAM and let users wire to it (e.g. https://wokwi.com/projects/393910195512969217), but the JPEG-output side is mocked: their simulator returns canned test patterns or static bitmaps. Wokwi doesn't expose the camera framework as a real video input. There's no public documentation describing how they did it, and the source isn't open.

Verdict: confirms that even commercial implementations stop at "fake the API, return something that compiles". That's the right scope for us too.

espressif/esp32-camera library

  • Repo: https://github.com/espressif/esp32-camera
  • Public API (header esp_camera.h):
    esp_err_t esp_camera_init(const camera_config_t *config);
    camera_fb_t* esp_camera_fb_get(void);
    void esp_camera_fb_return(camera_fb_t *fb);
    esp_err_t esp_camera_deinit(void);
    sensor_t* esp_camera_sensor_get(void);
    

camera_fb_t is:

typedef struct {
    uint8_t * buf;          // ptr to image data
    size_t   len;           // bytes in buf
    size_t   width;
    size_t   height;
    pixformat_t format;     // PIXFORMAT_JPEG / RGB565 / GRAYSCALE / …
    struct timeval timestamp;
} camera_fb_t;

This is the surface our shim needs to mimic. It's small. Almost every sample sketch only ever calls _init(), _fb_get(), _fb_return(). That's our minimum viable shim.

yoursunny/esp32cam (Arduino wrapper)

Thin C++ wrapper on top of the Espressif library. Internally calls the same esp_camera_* symbols. If we shim the C API, the Arduino wrapper works for free.

Browser-side webcam → frame stream

navigator.mediaDevices.getUserMedia({video:true}) returns a MediaStream; pipe it into a <video> element, draw it on a <canvas>, call canvas.toBlob('image/jpeg', quality), and you have a JPEG. There are dozens of working examples (websocket-webcam, getUserMedia samples, MDN "Taking still photos"). Frame rate of 515 fps is realistic for 320×240 with reasonable JPEG quality. See 03_browser_webcam_capture.md for the exact code we want.

Verdict: zero risk. This is a solved problem; it's just plumbing.

Closest precedents inside Velxio

The ESP32 sensor-attach pattern (DHT22, HC-SR04) is the closest precedent. Backend gets sensor data via a host channel, pushes it into the QEMU process as needed when the firmware reads from a peripheral register. See:

  • backend/app/services/esp32_lib_bridge.py
  • backend/app/services/esp_qemu_manager.py
  • frontend/src/store/useSimulatorStore.tsregisterSensor() / unregisterSensor() calls.

The camera is "just another sensor that returns a JPEG when polled" — the existing pattern fits as long as we're injecting at the library level, not the bus level. That's another point in favour of Path A.

Sources