Skip to content

Native MJPEG preview can show false frame-stall error after rotation #128

Description

@jeroenbaas

Summary

When SimulatorView uses its native MJPEG <img> mode, rotating the simulator can display the fatal frame-stall overlay even though the stream endpoint is actively producing frames.

The message is:

Stream is not producing frames. The simulator may have stopped - try reconnecting.

Environment

  • serve-sim@0.1.44
  • macOS 26.3 (25D125), Apple Silicon (Mac16,10)
  • Xcode 26.5 / iOS Simulator 26.5
  • iPad Air 11-inch (M4) simulator
  • Node v25.5.0
  • Chromium client on another machine on the LAN

Context

The default JavaScript frame-reader path was unusable because of #103, so a diagnostic patch selected the existing native MJPEG <img> path. A localhost MJPEG keepalive consumer was also attached to avoid the native startup crash described in #120. This meant the helper had multiple stream consumers.

Reproduction

  1. Start serve-sim with MJPEG capture.
  2. Render the existing native MJPEG <img> path in SimulatorView.
  3. Rotate the simulator from the toolbar.
  4. Wait for the liveness timeout.

Actual behavior

The frame-stall overlay appears after rotation. At the same time:

  • a fresh request to /stream.mjpeg returns HTTP 200;
  • the endpoint transferred about 9.4 MB in a four-second sample;
  • /config reflected the new orientation.

The capture service was therefore still producing frames.

Expected behavior

The native image should remain live or reconnect after the orientation/config change. A secondary stream consumer should not be able to mark the visible stream as dead while frames are still being produced.

Suspected cause

In native image mode, SimulatorView renders <img src=".../stream.mjpeg"> and starts a separate JavaScript fetch() of the same endless stream as a boundary watchdog. Either request can stall independently, so the watchdog can set the fatal error while the visible image and capture helper remain healthy.

PR #25 describes the same parallel-fetch false-positive risk and uses a plain <img> for grid mode to avoid it.

Possible direction

Use one native image stream consumer. Liveness could come from the /config frame counter, similar to the Safari support path, and the image URL could be refreshed when orientation/config changes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions