Jump to content

Movie Player

From OpenBOR
(Redirected from Movie get channel mask())

OpenBOR provides a reusable source, playback, and channel system for movie media. The API uses the generic movie_* namespace so additional container or codec support can be added later. The current backend plays WebM files containing VP8 video and optional Vorbis audio.

Movie playback and presentation are deliberately separate. OpenBOR advances active movies asynchronously, while creator scripts select one of two presentation paths:

  • movie_draw_to_screen() converts the retained YUV frame to 32-bit RGB and copies it into a creator-selected screen. This path supports subscreens, offsets, clipping, scaling, black filtering, and normal drawing order.
  • movie_draw_to_yuv() presents the retained frame directly through the hardware YUV output path. This avoids software YUV-to-RGB conversion and is intended for exclusive final-screen presentation.

Neither drawing function advances the movie clock or decoder. Playback, pause, position, speed, repeat, interruption, and embedded-audio controls remain properties of the movie channel regardless of the selected presentation path.

Choosing a presentation path

Neither path is universally superior. Hardware YUV presentation favors efficient, exclusive playback, while 32-bit RGB drawing favors composition and creative control.

Consideration movie_draw_to_yuv() movie_draw_to_screen()
YUV conversion Uploads the decoded Y, U, and V planes to the video backend. Where supported, the renderer or GPU performs YUV-to-RGB conversion and final scaling. Converts the decoded YUV frame into a 32-bit RGB OpenBOR screen before presentation.
CPU and memory cost Avoids the full software YUV-to-RGB conversion and intermediate RGB frame. This is especially useful for high-resolution or fullscreen movies. Uses additional CPU time and memory bandwidth for conversion, plus scaling when the requested dimensions differ from the source.
Display sizing Uses the WebM display dimensions by default, independently of the internal resolution configured by video.txt. Zero width and height follow the destination screen, making the movie naturally conform to a main screen or subscreen.
Composition Owns the final display while active. It cannot be mixed with normal OpenBOR drawing. May be placed anywhere in the normal drawing order and combined with sprites, text, effects, or other movie channels.
Screen effects Does not support destination offsets, clipping, black filtering, or later drawscreen() transformations. Supports offsets, clipping, black filtering, subscreens, and subsequent drawmethod transformations.
Typical use Fullscreen cinematics, high-resolution introductions, logos, and other movies intended to occupy the display by themselves. In-world screens, animated interfaces, picture-in-picture layouts, layered cutscenes, and movies requiring overlays or effects.

Both paths use the same WebM demuxer and VP8 decoder. Hardware YUV presentation reduces conversion and composition work after decoding; it does not eliminate video decoding cost. Actual acceleration depends on the active SDL or OpenGL video backend and the capabilities of the target system.

The movie system has three main parts:

  • Source - A streamed path or cached WebM byte buffer identified by a source ID.
  • Playback - One active use of a source, represented by a stable playback object pointer.
  • Movie channel - One of 64 fixed slots that owns playback, timing, decoding, and sound-routing state.

Keeping these concepts separate is important. One source may be played several times, each playback has independent state, movie channels are separate from the sound channels used by embedded audio, and destination screens remain under creator control.

Formats

Component Current support Notes
Container WebM The supplied path is used exactly. Movie loading does not append an extension.
Video VP8 Video track required. Stereoscopic WebM modes are not supported.
Audio Optional Vorbis, mono or stereo Embedded audio is decoded to 16-bit PCM and routed through an ordinary OpenBOR sound channel. Sample rates from 11.025 through 48 kHz are recommended.
Presentation 32-bit RGB or hardware YUV Retained frames may be converted to RGB and drawn into the main screen or any creator-owned 32-bit subscreen. They may instead be presented directly through the exclusive hardware YUV output path.

Source video dimensions must be at least 2 by 2, even on both axes, and small enough for the 32-bit screen renderer to represent safely. Compatibility is checked when the asynchronous decoder opens. Successful movie_load() calls only prove that the source path could be opened or cached.

Movie functions remain visible on builds compiled without WebM support. Such builds report that movie playback is unavailable and return an empty value instead of opening media.

Streamed and cached sources

movie_load() accepts a loading-mode constant.

Mode Constant Load behavior Playback behavior Best use
Streamed MOVIE_LOADING_STREAM Copies the path and confirms that the file can be opened. Each playback opens an independent packfile position and decoder. Long movies, one-time scenes, and memory-sensitive projects.
Cached MOVIE_LOADING_CACHE Reads the complete compressed WebM file into memory once. Each playback reads the shared read-only buffer but still owns an independent decoder and frame queues. Short clips, repeated playback, and seek-heavy controls when sufficient RAM is available.
Automatic MOVIE_LOADING_AUTO Caches when the file fits the engine's memory policy; otherwise keeps a streamed source. Uses the selected cached or streamed source transparently. General-purpose loading when a project does not need to force a policy.

Automatic mode allows cached sources to occupy at most one quarter of total system memory. It also preserves an available-memory reserve of at least one eighth of total memory or 128 MiB, whichever is larger. Cache allocation pressure falls back to streaming. File or pack I/O errors still fail the load instead of being hidden by a fallback.

Cached mode is a compressed source cache, not a decoded frame cache. It removes repeated storage reads but does not remove VP8 or Vorbis decoding cost.

Source storage grows dynamically from an initial capacity of 64 records. Source IDs are assigned in ascending order and are not reused during the session. Loading the same path more than once creates another source ID; OpenBOR does not merge duplicate movie-load requests automatically.

One source can back several simultaneous playbacks. Cached playbacks share the source bytes, while every playback retains independent position, speed, repeat, dimensions, offsets, movie channel, and sound channel state.

Movie channels

OpenBOR exposes one bank of 64 movie channels numbered 0 through 63.

  • Automatic playback selects the lowest inactive movie channel.
  • Automatic playback fails when all 64 channels are active.
  • Explicit channel selection forces playback onto that slot and stops its previous occupant.
  • Stopped or completed playback immediately releases its source reference and marks the channel inactive.
  • The 64-bit active mask allows OpenBOR and scripts to skip inactive channels.
  • Channel objects remain structurally stable until movie shutdown, even while their playback state is replaced or reset.

Movie channels have no priority system. Explicit selection is a forced replacement. The public constants MOVIE_CHANNEL_COUNT and MOVIE_CHANNEL_AUTO report the current capacity and automatic-selection value.

Practical limits

The 64-channel capacity provides consistency and creative headroom, not a realistic expectation of 64 simultaneous decoders. Every active movie may own demux, video-decoder, audio-decoder, packet-queue, frame-queue, conversion, scaling, and sound-stream resources. Available CPU time, memory bandwidth, storage speed, resolution, frame rate, and target hardware establish the practical limit.

Most projects should expect one or two simultaneous high-resolution movies to be a substantial workload. The fixed channel bank prevents an arbitrary API ceiling from becoming the first limitation.

Playback defaults

Every successful movie_play() begins with the following state:

Setting Default Behavior
Movie channel Automatic Uses the lowest inactive movie channel unless a channel is supplied.
Presentation target None Playback advances without drawing until a script calls movie_draw_to_screen() or movie_draw_to_yuv().
Width and height 0, 0 RGB drawing adopts the corresponding destination-screen dimensions. Hardware YUV presentation uses the WebM display dimensions. Explicit positive values select the requested presentation size.
X and Y offset 0, 0 Places the prepared frame at the destination origin.
Speed 1.0 Normal forward playback.
Paused 0 Playback clock and decoding advance normally.
Repeat 0 Stops when the movie reaches its terminal frame.
Interrupt 1 Normal movie-skip input stops playback.
Black filter 0 Exact RGB black remains unchanged.
Sound channel 0 Embedded Vorbis audio uses conventional music and media space.

Script playback

movie_load()

Loads a reusable movie source and returns its integer source ID.

int source_id = movie_load(
    string path,
    int loading
);
Argument Required Default Description
path Yes None Exact module path to a WebM source.
loading No MOVIE_LOADING_STREAM MOVIE_LOADING_STREAM, MOVIE_LOADING_CACHE, or MOVIE_LOADING_AUTO.

Invalid paths, loading modes, allocation failures, or empty cached files fail with a script error.

movie_unload()

Releases a loaded source.

movie_unload(int source_id);

The source must exist and have no active playback references. Stop every playback using the source before unloading it. Unloaded IDs remain invalid and are not reassigned later in the session.

movie_play()

Starts a source and returns its stable movie playback object.

void playback = movie_play(
    int source_id,
    int movie_channel
);
Argument Required Default Description
source_id Yes None Source returned by movie_load().
movie_channel No MOVIE_CHANNEL_AUTO Omit the argument or pass NULL() for automatic allocation. Values from 0 through 63 force that channel.

Forced selection stops the current channel occupant before opening the new playback. Automatic selection never replaces an active movie and fails when no channel is free.

Decoder opening is asynchronous. movie_play() returns after the channel has been acquired and playback startup has been scheduled; the first drawable frame may arrive on a later update. A decoder or track error reported afterward stops that playback and appears clearly in the engine log.

The returned pointer identifies the channel object, not a permanent unique playback instance. Later forced playback on the same channel reuses the same pointer with new state.

movie_stop()

Stops playback, begins decoder teardown, releases its source reference, and recycles its movie channel.

movie_stop(void playback);

Calling movie_stop() with a valid but already inactive channel object safely leaves it inactive.

Basic example

This example starts a movie asynchronously, draws its current frame into a creator-owned screen, adds an overlay, and submits the completed screen through the ordinary renderer.

Initialization:

void movie_screen = allocscreen(360, 204);

int source_id = movie_load(
    "data/scenes/intro.webm",
    openborconstant("MOVIE_LOADING_AUTO")
);

void playback = movie_play(source_id);
int movie_channel = movie_get_channel_index(playback);

Drawing update:

if(movie_get_property(
    playback,
    openborconstant("MOVIE_PROPERTY_ACTIVE")
))
{
    clearscreen(movie_screen);
    movie_draw_to_screen(movie_screen, movie_channel);
    drawstringtoscreen(movie_screen, 4, 4, 0, "PLAYING");
    drawscreen(movie_screen, 80, 30, 5000);
}

The source can be unloaded after playback stops:

if(!movie_get_property(
    playback,
    openborconstant("MOVIE_PROPERTY_ACTIVE")
))
{
    movie_unload(source_id);
}

Screen composition

Creator-controlled drawing

Movie playback never stores or owns a destination screen. Call movie_draw_to_screen() whenever the retained frame should be copied into a screen:

movie_draw_to_screen(
    void screen,
    int movie_channel
);

The screen must be a valid 32-bit OpenBOR screen. The second argument is the movie channel index, not the playback pointer. Save the result of movie_get_channel_index(), read MOVIE_PROPERTY_CHANNEL, or use a known explicitly selected channel.

Drawing and playback are independent:

  • Calling movie_draw_to_screen() does not advance the movie clock or decoder.
  • Failing to draw does not pause playback. The movie continues in the background.
  • The first few calls may draw nothing while asynchronous decoder startup or seek preroll is still in progress.
  • Repeated calls copy the retained current frame. The same channel may be drawn to several screens during one update.
  • OpenBOR does not clear, submit, resize, or free the destination screen.

Call movie_draw_to_screen() only while the channel is active. An invalid screen, inactive channel, or out-of-range channel reports a script error.

Hardware YUV presentation

Call movie_draw_to_yuv() to present a retained movie frame directly through the hardware YUV output path:

movie_draw_to_yuv(int movie_channel);

The argument is the movie channel index, not the playback pointer. Save the result of movie_get_channel_index(), read MOVIE_PROPERTY_CHANNEL, or use a known explicitly selected channel.

Hardware YUV presentation bypasses software conversion to a 32-bit OpenBOR screen. SDL renderer builds upload the Y, U, and V planes to a streaming YUV texture. OpenGL builds upload the planes independently and perform YUV-to-RGB conversion in the fragment shader.

Calling movie_draw_to_yuv() does not advance playback. Call it whenever a newly retained frame should be presented. Calls made before the first decoded frame becomes available succeed without displaying anything.

The hardware path is an exclusive final-output operation. It replaces the normal game output texture for the duration of YUV presentation and presents directly to the display. Consequently:

  • It does not accept an s_screen destination.
  • It cannot draw into a subscreen.
  • It does not participate in sprite or screen composition order.
  • It cannot layer text, sprites, boxes, or effects over the movie.
  • MOVIE_PROPERTY_OFFSET_X and MOVIE_PROPERTY_OFFSET_Y do not apply.
  • MOVIE_PROPERTY_BLACK_FILTER does not apply.
  • Only one movie channel can occupy the hardware output at a time.
  • Stopping or completing the YUV-presented movie restores the configured OpenBOR video mode automatically.

Playback controls remain fully available because they belong to the movie channel rather than the presentation path. Scripts may pause, resume, seek, change speed, enable repeat, read position, change sound routing, or stop a movie presented through hardware YUV.

Hardware YUV sizing

MOVIE_PROPERTY_WIDTH and MOVIE_PROPERTY_HEIGHT also select the logical display dimensions used by hardware YUV presentation.

  • Zero uses the corresponding WebM display dimension.
  • MOVIE_SIZE_NATIVE also uses the WebM display dimension.
  • Other positive values request that display dimension explicitly.
  • Width and height remain independent, so creators may intentionally change the aspect ratio.

The decoded YUV texture retains the source frame dimensions. Width and height control its displayed size rather than forcing an intermediate software RGB conversion.

Hardware YUV example

int source_id = movie_load(
    "data/scenes/intro.webm",
    openborconstant("MOVIE_LOADING_STREAM")
);

void playback = movie_play(source_id);
int channel = movie_get_channel_index(playback);

movie_set_property(
    playback,
    openborconstant("MOVIE_PROPERTY_WIDTH"),
    openborconstant("MOVIE_SIZE_NATIVE")
);

movie_set_property(
    playback,
    openborconstant("MOVIE_PROPERTY_HEIGHT"),
    openborconstant("MOVIE_SIZE_NATIVE")
);

// Call during the drawing update while playback is active.
movie_draw_to_yuv(channel);

Pause, seek, speed, and stop controls use the same playback object:

movie_set_property(
    playback,
    openborconstant("MOVIE_PROPERTY_PAUSED"),
    1
);

movie_set_property(
    playback,
    openborconstant("MOVIE_PROPERTY_POSITION"),
    30000
);

movie_set_property(
    playback,
    openborconstant("MOVIE_PROPERTY_PAUSED"),
    0
);

// Later:
movie_stop(playback);

Drawing order

The location of movie_draw_to_screen() in creator code determines composition order. Nothing is injected automatically before or after the sprite queue.

For a typical creator-owned subscreen:

  1. Clear or prepare the destination screen.
  2. Draw any background content that belongs below the movie.
  3. Call movie_draw_to_screen().
  4. Draw text, sprites, boxes, or effects that belong over the movie.
  5. Submit the completed screen with drawscreen().

Calling two movie channels against the same screen follows normal call order. The second call overwrites the first where their destination rectangles overlap. This makes layering explicit and independent of channel numbers.

The destination's normal drawscreen() drawmethod remains available for whole-screen rotation, scaling, flipping, blending, or other later composition.

Main screen and subscreens

Use allocscreen(width, height) for a creator-owned 32-bit subscreen. Use openborvariant("vscreen") when a suitable drawing hook must address the engine's main screen directly:

void main_screen = openborvariant("vscreen");
movie_draw_to_screen(main_screen, movie_channel);

Direct main-screen drawing follows the same rule as every other screen operation: later engine or script drawing may cover it, and a later clear erases it. A subscreen usually provides the most predictable choice when a movie is part of a larger creator-controlled layout.

Changing destinations only means passing a different screen to the next draw call. Playback keeps no screen pointer between calls.

Width, height, offsets, and clipping

MOVIE_PROPERTY_WIDTH and MOVIE_PROPERTY_HEIGHT independently select the prepared frame dimensions.

  • Zero width uses the destination screen width at draw time.
  • Zero height uses the destination screen height at draw time.
  • MOVIE_SIZE_NATIVE uses the decoded video's native dimension.
  • Other positive values scale the decoded frame to the requested dimension.
  • Width and height may be set independently, so scripts are responsible for preserving aspect ratio when desired.

MOVIE_PROPERTY_OFFSET_X and MOVIE_PROPERTY_OFFSET_Y place the scaled frame inside the destination. Offsets are signed. Pixels outside the destination are clipped safely.

Scaling a movie larger than its destination and applying negative offsets provides a controllable zoom-and-crop effect. Scaling it smaller provides picture-in-picture placement.

These composition rules describe movie_draw_to_screen(). Hardware YUV presentation does not have a destination screen. Its width and height select the logical display dimensions, while offsets, clipping, and black filtering do not apply.

Zoom-and-crop example

This example prepares a 320 by 180 movie image and clips its central 160 by 90 region into a subscreen.

void screen = allocscreen(160, 90);
int source_id = movie_load("data/scenes/camera.webm");
void playback = movie_play(source_id);
int channel = movie_get_channel_index(playback);

movie_set_property(
    playback,
    openborconstant("MOVIE_PROPERTY_WIDTH"),
    320
);

movie_set_property(
    playback,
    openborconstant("MOVIE_PROPERTY_HEIGHT"),
    180
);

movie_set_property(
    playback,
    openborconstant("MOVIE_PROPERTY_OFFSET_X"),
    -80
);

movie_set_property(
    playback,
    openborconstant("MOVIE_PROPERTY_OFFSET_Y"),
    -45
);

clearscreen(screen);
movie_draw_to_screen(screen, channel);
drawscreen(screen, 80, 30, 5000);

Multiple destinations example

One playback may feed several compositions without additional decoding. This example draws the same retained frame full-size into one screen and again into a smaller screen whose dimensions are selected by the playback properties.

movie_set_property(
    playback,
    openborconstant("MOVIE_PROPERTY_WIDTH"),
    0
);

movie_set_property(
    playback,
    openborconstant("MOVIE_PROPERTY_HEIGHT"),
    0
);

movie_draw_to_screen(large_screen, movie_channel);
movie_draw_to_screen(small_screen, movie_channel);

Zero dimensions are resolved separately for each destination. Both calls use the same decoded current frame.

Exact-black protection

Some subscreen composition paths treat RGB 0, 0, 0 as a transparency mask. Enable MOVIE_PROPERTY_BLACK_FILTER to protect exact-black movie pixels:

movie_set_property(
    playback,
    openborconstant("MOVIE_PROPERTY_BLACK_FILTER"),
    1
);

When enabled, OpenBOR changes only exact RGB 0, 0, 0 movie pixels to RGB 1, 1, 1 after YUV conversion. Other near-black shades remain unchanged. The filter affects the prepared movie frame before scaling and composition.

The filter is disabled by default because not every composition path uses exact black as transparency.

Playback timing and control

Movie control is provided through the property API. Timing properties use milliseconds. Playback controls belong to the movie channel and work with both movie_draw_to_screen() and movie_draw_to_yuv().

Embedded audio owns the master playback clock when an audio track is present. Video presentation follows that clock, and sufficiently late decoded frames may be discarded to preserve synchronization. Video-only sources use the movie playback clock directly. Drawing is still creator-controlled and does not change either clock.

Position and seeking

MOVIE_PROPERTY_POSITION reports the current playback position as an unsigned 64-bit millisecond value. Writing it schedules an asynchronous seek and decoder reopen at the requested position.

MOVIE_PROPERTY_DURATION reports the source duration in milliseconds and is read-only. Seeking at or beyond a known duration clamps the request to the final available millisecond.

int position_id = openborconstant("MOVIE_PROPERTY_POSITION");

movie_set_property(playback, position_id, 30000); // 30 seconds

Seeking preserves the last prepared frame until a replacement frame is ready. Streamed seek latency depends on storage performance and WebM keyframe placement. Cached mode can reduce storage latency but still performs decoder work.

Seeking is also the intended way to move backward. Reverse playback is not supported.

Pause

MOVIE_PROPERTY_PAUSED accepts zero or nonzero values. Pausing freezes the movie clock, preserves the current frame, and pauses embedded audio. Resuming continues from the stored position.

Speed and fast-forward

MOVIE_PROPERTY_SPEED accepts a decimal from 0.0 through 16.0. Negative values are rejected.

Speed Video behavior Embedded-audio behavior
1.0 Normal forward playback. Normal speed and pitch.
Greater than 1.0 Fast-forward. Speed and pitch increase with the positive rate.
Between 0.0 and 1.0 Slow forward playback. Speed and pitch decrease with the positive rate.
0.0 Holds the current position and frame. Paused.
int speed_id = openborconstant("MOVIE_PROPERTY_SPEED");

movie_set_property(playback, speed_id, 2.0); // Fast-forward
movie_set_property(playback, speed_id, 1.0); // Normal

Use MOVIE_PROPERTY_POSITION for rewind controls or other backward navigation.

Repeat

MOVIE_PROPERTY_REPEAT accepts zero or nonzero values. Playback reopens at the beginning after its terminal frame.

Movie playback has no separate repeat offset. Scripts can implement custom loop regions by observing position and writing a new position.

Input interruption

MOVIE_PROPERTY_INTERRUPT defaults to 1. New Escape or normal movie-skip button presses stop playback during the engine update.

Set the property to 0 when playback must continue until natural completion or an explicit movie_stop() call:

movie_set_property(
    playback,
    openborconstant("MOVIE_PROPERTY_INTERRUPT"),
    0
);

Embedded audio

Movie channels and sound channels are independent address spaces.

  • Movie channels range from 0 through 63 and own video playback objects.
  • Sound channels range from 0 through 4095 and mix audio.
  • Every new movie playback initially routes embedded audio to sound channel 0.
  • Modern movie_play() playback replaces only its selected sound channel. It does not stop unrelated sound channels.
  • WebM sources without an audio track leave existing sound playback unchanged.
  • Failure to open an otherwise optional audio track leaves the video playing silently and reports the failure in the log.

Channel 0 is OpenBOR's soft-reserved music and media channel. Starting a movie with embedded audio therefore replaces the current occupant of sound channel 0 unless the movie has already been routed elsewhere.

movie_set_sound_channel()

Moves a playback's embedded audio to an explicit sound channel.

movie_set_sound_channel(
    void playback,
    int sound_channel
);

Valid sound channels are 0 through 4095. Changing the sound channel schedules a decoder reopen at the current movie position so video and audio remain synchronized. The selected sound channel is forced: an existing occupant is replaced without a priority check.

The sound-channel property is read-only through movie_set_property(). Use movie_set_sound_channel() to change routing.

Route each movie to its intended sound channel immediately after starting it and before starting the next audible movie:

int source_a = movie_load("data/scenes/feed_a.webm");
int source_b = movie_load("data/scenes/feed_b.webm");

void movie_a = movie_play(source_a, 4);
movie_set_sound_channel(movie_a, 10);

void movie_b = movie_play(source_b, 5);
movie_set_sound_channel(movie_b, 11);

The embedded streams are ordinary producer-fed sound objects. Scripts may inspect their volume, pause state, play ID, and other applicable common properties through the sound object API. Sample-backed seeking properties do not apply to producer-fed movie audio; seek through MOVIE_PROPERTY_POSITION instead.

Movie object script API

Advanced scripts may inspect the fixed movie channel bank, obtain stable channel objects, and read or change playback properties.

Use named constants from openborconstant(). Raw numeric property and mode IDs are implementation details.

movie_get_channel_mask()

mixed active_mask = movie_get_channel_mask();

Returns an unsigned 64-bit mask. Bit 0 represents movie channel 0, bit 1 represents channel 1, and so on. Set bits indicate active playback.

movie_get_channel_object()

void playback = movie_get_channel_object(int movie_channel);

Returns the stable movie object for a channel from 0 through 63. The fixed bank exists after movie-system initialization, so inactive channels still return objects. Test MOVIE_PROPERTY_ACTIVE or the active mask before treating the object as current playback.

movie_get_channel_index()

int movie_channel = movie_get_channel_index(void playback);

Validates a movie object pointer and returns its channel index.

Property access

mixed value = movie_get_property(
    void playback,
    int property
);

movie_set_property(
    void playback,
    int property,
    mixed value
);

Property reads use a synchronized public-state snapshot. Playback-sensitive writes route through lifecycle-aware helpers so clocks, decoders, frame scaling, and audio remain coherent.

Property constant Type Access Default Description
MOVIE_PROPERTY_ACTIVE Integer Read 0 before play 1 while the channel owns active playback; otherwise 0.
MOVIE_PROPERTY_BLACK_FILTER Integer Read/write 0 Converts exact RGB black movie pixels to RGB 1, 1, 1.
MOVIE_PROPERTY_CHANNEL Integer Read Channel index Stable movie channel from 0 through 63.
MOVIE_PROPERTY_DURATION Unsigned 64-bit integer Read Source value Duration in milliseconds.
MOVIE_PROPERTY_HEIGHT Unsigned 64-bit integer Read/write 0 Prepared frame height. Zero uses destination height; MOVIE_SIZE_NATIVE uses native video height.
MOVIE_PROPERTY_INTERRUPT Integer Read/write 1 Nonzero allows normal movie-skip input to stop playback.
MOVIE_PROPERTY_OFFSET_X Integer Read/write 0 Signed horizontal destination offset. Overflow is clipped.
MOVIE_PROPERTY_OFFSET_Y Integer Read/write 0 Signed vertical destination offset. Overflow is clipped.
MOVIE_PROPERTY_PAUSED Integer Read/write 0 Pause state. Writes require active playback.
MOVIE_PROPERTY_POSITION Unsigned 64-bit integer Read/write 0 Current millisecond position. Writing seeks active playback.
MOVIE_PROPERTY_REPEAT Integer Read/write 0 Nonzero repeats at the source boundary.
MOVIE_PROPERTY_SOUND_CHANNEL Integer Read 0 Generic sound channel used by embedded audio. Change with movie_set_sound_channel().
MOVIE_PROPERTY_SOURCE Integer Read -1 while inactive Source ID owned by the current playback.
MOVIE_PROPERTY_SPEED Decimal Read/write 1.0 Forward playback speed from 0.0 through 16.0.
MOVIE_PROPERTY_WIDTH Unsigned 64-bit integer Read/write 0 Prepared frame width. Zero uses destination width; MOVIE_SIZE_NATIVE uses native video width.

Property example

This example pauses an active playback, seeks to 12.5 seconds, disables skip input, and resumes at half speed.

if(movie_get_property(
    playback,
    openborconstant("MOVIE_PROPERTY_ACTIVE")
))
{
    movie_set_property(
        playback,
        openborconstant("MOVIE_PROPERTY_PAUSED"),
        1
    );

    movie_set_property(
        playback,
        openborconstant("MOVIE_PROPERTY_POSITION"),
        12500
    );

    movie_set_property(
        playback,
        openborconstant("MOVIE_PROPERTY_INTERRUPT"),
        0
    );

    movie_set_property(
        playback,
        openborconstant("MOVIE_PROPERTY_SPEED"),
        0.5
    );

    movie_set_property(
        playback,
        openborconstant("MOVIE_PROPERTY_PAUSED"),
        0
    );
}

Legacy playback

Traditional WebM entry points remain available as wrappers around the movie system. Their defaults intentionally reproduce historical blocking fullscreen behavior.

playwebm()

int result = playwebm(
    string path,
    int noskip
);
Argument Required Default Description
path Yes None Exact WebM source path.
noskip No 0 Zero permits normal skip input. Nonzero forces playback to continue until completion or error.

Return values:

Result Meaning
1 Playback completed normally.
0 Loading, decoding, rendering, or cleanup failed.
-1 Creator-enabled input interrupted playback.

The wrapper performs the following operations:

  • Stops every active movie playback.
  • Loads the requested source in streamed mode.
  • Uses automatic movie-channel selection.
  • Uses normal speed, no repeat, and sound channel 0.
  • Sets width and height to MOVIE_SIZE_NATIVE.
  • Blocks the calling scene or script until completion, interruption, or error.
  • Presents each available frame through the hardware YUV output path.
  • Uses the WebM display dimensions instead of scaling through the resolution configured by video.txt.
  • Captures screenshots from a native-resolution 32-bit conversion of the current YUV frame.
  • Restores the configured OpenBOR video mode when playback ends.
  • Unloads its temporary source before returning.
  • Preserves the historical replace-all sound behavior when the WebM contains audio.

Legacy WebM files with embedded audio stop current music and active sample playback before opening a producer-fed stream on sound channel 0. Legacy WebM files without audio leave existing channel 0 playback running.

Scene video command

Scene files retain their existing command:

video {path} {skipone} {noskip}

noskip uses the same interruption rule as playwebm(). When interruption is enabled, skipone controls whether an interrupted video allows the scene parser to continue instead of closing the remaining scene.

Projects requiring asynchronous playback, seeking, speed control, repeat, caching, multiple movie channels, or separate sound routing should use the movie_* API. Use movie_draw_to_screen() when the movie must participate in normal screen composition. Use movie_draw_to_yuv() for exclusive hardware-accelerated presentation. Traditional playwebm() and the scene video command remain appropriate for intentionally blocking, native-size hardware YUV playback.

Practical guidance

  • Use movie_draw_to_yuv() when the movie should own the final display and software RGB conversion or video.txt scaling is undesirable.
  • Use movie_draw_to_screen() when sprites, text, effects, subscreens, offsets, clipping, black filtering, or deliberate layer order are required.
  • Do not alternate hardware YUV presentation between several movie channels as a composition technique. The hardware output is exclusive.
  • Width and height affect both paths, but zero dimensions resolve differently: RGB drawing follows the destination screen, while hardware YUV presentation follows the WebM display dimensions.
  • Stop the YUV-presented playback normally. OpenBOR restores the configured game video mode automatically.
  • Use MOVIE_LOADING_AUTO for a safe general-purpose cache decision.
  • Stream long or one-time movies when complete caching would waste RAM.
  • Cache short, frequently reused, or seek-heavy clips when storage latency matters and sufficient memory is available.
  • Remember that cached sources still require full VP8 and Vorbis decoding for every playback.
  • Draw into a creator-owned subscreen when sprites, text, effects, or other screen drawing must share a deliberate layer order with the movie.
  • Clear or prepare each destination before drawing the movie. OpenBOR never clears a creator-owned screen automatically.
  • Draw active movies regularly while they are visible. Playback continues even when no draw call is made.
  • Treat zero width and height as per-destination fill behavior. Use MOVIE_SIZE_NATIVE for native dimensions or explicit values for picture-in-picture layouts.
  • Use signed offsets with oversized dimensions for controlled zoom and clipping.
  • Enable the black filter only when exact black must survive a subscreen transparency mask.
  • Route simultaneous movies to distinct sound channels immediately after each movie_play() call.
  • Use seeks for rewind or other backward navigation; negative playback speed is not supported.
  • Stop every playback using a source before calling movie_unload().
  • Treat movie pointers as stable channel slots rather than permanent unique playback instances.
  • Use the 64-channel mask as a fast state summary, not as a target workload.
  • Prefer the modern movie API for new projects. Reserve playwebm() and the scene video command for compatibility or intentionally blocking presentation.