Skip to content

Video Playback

VideoPlayer provides full-window MP4 playback through AppContext. It is intended for intro movies, cutscenes, and other video that temporarily overlays the rendered game.

The API is available when SNOWPULSE_HAS_VIDEO is enabled. Actual playback is controlled by the SNOWPULSE_ENABLE_MP4_VIDEO CMake option, which defaults to ON. The PLAYABLE_AD web profile removes the video API entirely.

Platform Support

Platform Backend Status
macOS desktop AVFoundation (AVPlayer) Supported
Windows desktop No encoder/player backend Unavailable
Web Browser <video> overlay Supported
iOS AVFoundation (AVPlayer) Supported
Android Media3 ExoPlayer asset:/// overlay Supported

Videos are resolved relative to AppContext::assetRoot() unless the supplied path is already absolute. Apple native backends require a local file. Android requires a valid packaged-asset path and passes an asset:/// URI to Media3. Web playback first checks Emscripten's virtual filesystem and creates an MP4 object URL when the file is mounted; otherwise it treats the path as a browser URL.

Playback Lifecycle

#if SNOWPULSE_HAS_VIDEO
auto* video = context()->videoPlayer();
if (video && video->load("video/intro.mp4")) {
    // load() is asynchronous. Wait for ReadyPaused before playing.
}

// In scene update:
if (video && video->state() == snowpulse::VideoPlaybackState::ReadyPaused) {
    video->play();
}
#endif

VideoPlaybackState has these values:

  • Unavailable: no loaded video or no platform backend.
  • Loading: the backend is preparing the asset.
  • ReadyPaused: the first frame is ready and playback may begin.
  • Playing: playback is active.
  • Ended: playback reached the end.
  • Failed: loading or playback failed.

App calls VideoPlayer::update() once per active frame, so game code normally only needs to poll state(). play() and pause() return false when the current state does not allow the requested transition. stop() removes the overlay and returns to Unavailable.

Use setVisible(false) to hide the video overlay without stopping playback. The native overlays do not consume pointer input. On web, the overlay handles a tap while ReadyPaused so mobile browsers can satisfy their user-activation requirement and retry a play() rejected by autoplay policy.

Android Media3 work runs on the Activity main thread. Pause and destruction release or suspend the player without callbacks reaching destroyed C++ state; the overlay has no controls and sits above the GLES surface.

Portal Pause Behavior

When Playgama or YouTube reports a portal pause, App pauses a playing video. It resumes the video only if the portal was responsible for pausing it. A video that game code had already paused remains paused.

Build Configuration

Disable MP4 playback for builds that do not use it:

cmake -S . -B cmake-build-release \
    -DCMAKE_BUILD_TYPE=Release \
    -DSNOWPULSE_ENABLE_MP4_VIDEO=OFF

This leaves VideoPlayer present in a full-profile build, but operations report Unavailable. In PLAYABLE_AD, SNOWPULSE_HAS_VIDEO=0, so the service and umbrella include are compile-time gated.