Table of Contents

Simple Playback

The SimplePlaybackPage demonstrates media playback from a remote or local source using MediaPlayer. It covers stream and file playback, video and audio track selection, seeking, playback speed control, and live stream statistics.

Overview

The SimplePlaybackPage performs the following:

  1. Plays media from a URI (RTSP, RTMP, SRT, HLS, HTTP, file path, etc.) using MediaPlayer
  2. Enumerates available video and audio tracks after playback starts
  3. Allows switching between tracks at runtime
  4. Provides seeking with a position slider for on-demand content
  5. Supports playback speed control — pause, rewind, and fast-forward
  6. Displays absolute playback time with latency and jitter statistics for live streams

Starting Playback

this.player.AudioStreamIndex = VAST.Player.MediaPlayer.TRACK_AUTO;
this.player.VideoStreamIndex = VAST.Player.MediaPlayer.TRACK_AUTO;
this.player.Source = new Uri(this.tboxUri.Text);
this.player.Play();

Track indices are set to TRACK_AUTO for automatic selection. The Source property accepts any URI supported by the VASTreaming engine. Play() begins asynchronous connection and playback.

If the player is already playing at a non-standard speed (rewind or fast-forward), pressing Play resets the playback rate to 1.0 instead of restarting.

Track Selection

When the player first reaches the Playing state, available tracks are enumerated and populated into picker controls:

for (int i = 0; i < this.player.VideoStreamCount; ++i)
{
    VAST.Common.MediaType mt = this.player.GetVideoMediaType(i);
    tracks.Add(mt.ToString().Substring(6));
}

Each track is described by its MediaType (codec, resolution, bitrate, etc.). Selecting a track in the picker switches the active stream at runtime:

this.player.VideoStreamIndex = this.pickerVideoTrack.SelectedIndex;

Seeking

For seekable media (player.CanSeek), the position slider range is set to the media duration in milliseconds. When the user completes a drag, the player seeks to the new position:

this.player.Position = new TimeSpan((long)this.sliderPosition.Value * 10000);

A 100 ms timer updates the slider and time label during playback. Timer-driven updates are suppressed while the user is dragging the slider thumb to prevent conflicts.

Playback Speed Control

The page provides rewind and fast-forward controls that modify the playback rate:

Action Behavior
Rewind (first press) Sets rate to -1.0
Rewind (subsequent) Doubles the negative rate (-2, -4, -8, -16, -32)
Fast-forward (while reversing) Resets rate to 1.0
Fast-forward (subsequent) Doubles the positive rate (2, 4, 8, 16, 32)
Play (while speed changed) Resets rate to 1.0

Pause toggles between Playing and Paused states via player.Pause() and player.Play().

Live Stream Statistics

For non-seekable (live) streams, the timer displays the absolute playback time along with latency and jitter statistics:

var stat = this.player.CurrentStatistics;
this.labelPosition.Text = string.Format("{0:yyyy-MM-dd HH:mm:ss.fff}{1}",
    this.player.AbsolutePlaybackTime.Value.ToLocalTime(),
    ((stat != null && stat.AverageLatency != null)
        ? $", latency {stat.AverageLatency.Value.TotalMilliseconds:0}±{stat.AverageJitter.Value.TotalMilliseconds:0} ms"
        : ""));

AbsolutePlaybackTime provides the wall-clock time of the currently rendered frame. CurrentStatistics reports the average end-to-end latency and jitter in milliseconds.

Absolute playback time is only available if the source stream provides timing information — for example, an RTSP stream with NTP timestamps via RTCP, an RTMP stream with onFI data, or an HLS stream with #EXT-X-PROGRAM-DATE-TIME tags.

Stopping Playback

this.player.Stop();
this.player.SourceMedia = null;

Stop() halts playback and SourceMedia = null releases the underlying media source. The page also stops playback automatically when the user navigates away.

Error Handling

The player fires MediaFailed when a connection or decoding error occurs. The handler stops playback and displays the error:

this.player.MediaFailed += (object sender, VAST.Media.ErrorEventArgs e) =>
{
    MainThread.BeginInvokeOnMainThread(() =>
    {
        this.stop();
        // display e.ErrorDescription
    });
};

MediaEnded is fired when the media reaches the end of the stream, triggering the same cleanup.

Send Log

The page includes a Send Log button that uploads the application log file to VASTreaming support for diagnostics:

await VAST.Common.License.SendLog("MAUI simple playback issue");

SendLog sends the current log file to the support server. A valid license key must be configured for this feature to work.

See Also