Skip to content

Loop Mode and Position Range Playback

This guide explains how to use loop mode and custom start-stop position (position range) features in the Media Player SDK for both MediaPlayerCore (DirectShow engine) and MediaPlayerCoreX (GStreamer engine).

Overview

Both Media Player engines support:

  • Loop Mode: Automatically restart playback when media reaches the end
  • Position Range: Play only a specific segment of media between start and stop positions
  • Combined Mode: Loop a specific segment of media continuously

These features are useful for:

  • Creating video loops for kiosks or displays
  • Preview playback of specific segments
  • Testing specific portions of media files
  • Creating seamless background video loops
  • Educational applications showing repeated content

MediaPlayerCore (DirectShow Engine)

MediaPlayerCore is the Windows-only DirectShow-based media player engine.

Loop Mode Properties

Loop Property

Enables or disables automatic loop playback.

// Enable loop mode
mediaPlayer.Loop = true;

// Disable loop mode
mediaPlayer.Loop = false;

Default value: false

Behavior: - When enabled, playback automatically restarts from the beginning when the end is reached - The OnLoop event fires each time playback restarts - For playlists, loops the entire playlist, not individual files

Loop_DoNotSeekToBeginning Property

Controls whether to seek to the beginning when loop restarts.

// Restart without seeking to beginning (seamless loop)
mediaPlayer.Loop_DoNotSeekToBeginning = true;

// Seek to beginning before restarting (default)
mediaPlayer.Loop_DoNotSeekToBeginning = false;

Default value: false

Behavior: - Only affects behavior when Loop is true - When true, restarts from current position without seeking - Improves performance and avoids visual glitches during loop transitions - Useful for seamless looping of content

Position Range Properties

Selection_Active Property

Enables or disables playback range selection.

// Enable position range playback
mediaPlayer.Selection_Active = true;

// Disable position range playback (play entire file)
mediaPlayer.Selection_Active = false;

Default value: false

Behavior: - When active, playback is constrained between Selection_Start and Selection_Stop - The player automatically stops or loops when reaching Selection_Stop - Useful for playing specific segments or creating clip previews

Selection_Start Property

Sets the start position for range-based playback.

// Start playback at 30 seconds
mediaPlayer.Selection_Start = TimeSpan.FromSeconds(30);

// Start playback at 2 minutes 15 seconds
mediaPlayer.Selection_Start = new TimeSpan(0, 2, 15);

Type: TimeSpan

Requirements: - Only used when Selection_Active is true - Must be less than Selection_Stop - Must be within media duration - The player automatically seeks to this position when starting

Selection_Stop Property

Sets the end position for range-based playback.

// Stop playback at 1 minute
mediaPlayer.Selection_Stop = TimeSpan.FromSeconds(60);

// Play to the end of file
mediaPlayer.Selection_Stop = TimeSpan.Zero;

Type: TimeSpan

Requirements: - Only used when Selection_Active is true - Must be greater than Selection_Start - Use TimeSpan.Zero to play to the end of the media file - When playback reaches this position, it stops (or loops if Loop is enabled)

MediaPlayerCore Events

OnLoop Event

Fires each time playback restarts in loop mode.

mediaPlayer.OnLoop += (sender, e) =>
{
    Console.WriteLine("Playback looped!");
    // Update loop counter, perform actions at loop point, etc.
};

When it fires: - Only when Loop property is true - Each time playback cycles from end to beginning - After seeking to the beginning (if applicable)

Use cases: - Track loop iterations - Update loop counters in UI - Perform actions at each loop point - Log playback statistics

Code Examples for MediaPlayerCore

Example 1: Basic Loop Mode

using VisioForge.Core.MediaPlayer;
using VisioForge.Core.Types;

// Create media player instance
var player = new MediaPlayerCore();

// Enable loop mode
player.Loop = true;

// Subscribe to loop event
player.OnLoop += (sender, e) =>
{
    Console.WriteLine($"Loop iteration at {DateTime.Now}");
};

// Set source and play
player.Playlist_Clear();
player.Playlist_Add(@"C:\Videos\sample.mp4");
await player.PlayAsync();

Example 2: Seamless Loop Without Seeking

using VisioForge.Core.MediaPlayer;

var player = new MediaPlayerCore();

// Enable seamless loop (no seeking to beginning)
player.Loop = true;
player.Loop_DoNotSeekToBeginning = true;

player.Playlist_Clear();
player.Playlist_Add(@"C:\Videos\background.mp4");
await player.PlayAsync();

Example 3: Play Specific Segment

using VisioForge.Core.MediaPlayer;

var player = new MediaPlayerCore();

// Enable position range
player.Selection_Active = true;

// Play from 1 minute to 2 minutes
player.Selection_Start = TimeSpan.FromMinutes(1);
player.Selection_Stop = TimeSpan.FromMinutes(2);

player.Playlist_Clear();
player.Playlist_Add(@"C:\Videos\long-video.mp4");
await player.PlayAsync();

Example 4: Loop Specific Segment

using VisioForge.Core.MediaPlayer;

var player = new MediaPlayerCore();

// Enable both loop and position range
player.Loop = true;
player.Selection_Active = true;

// Loop segment from 30 to 45 seconds
player.Selection_Start = TimeSpan.FromSeconds(30);
player.Selection_Stop = TimeSpan.FromSeconds(45);

// Track loop count
int loopCount = 0;
player.OnLoop += (sender, e) =>
{
    loopCount++;
    Console.WriteLine($"Segment loop #{loopCount}");
};

player.Playlist_Clear();
player.Playlist_Add(@"C:\Videos\video.mp4");
await player.PlayAsync();

Example 5: Dynamic Position Range Update

using VisioForge.Core.MediaPlayer;

var player = new MediaPlayerCore();

player.Selection_Active = true;
player.Selection_Start = TimeSpan.FromSeconds(10);
player.Selection_Stop = TimeSpan.FromSeconds(20);

player.Playlist_Clear();
player.Playlist_Add(@"C:\Videos\video.mp4");
await player.PlayAsync();

// Later, during playback, update the range
await Task.Delay(5000);

// Change to different segment
player.Selection_Start = TimeSpan.FromSeconds(30);
player.Selection_Stop = TimeSpan.FromSeconds(40);

// Seek to new start position
player.Position_Set_Time(player.Selection_Start);

MediaPlayerCoreX (GStreamer Engine)

MediaPlayerCoreX is the cross-platform GStreamer-based media player engine, supporting Windows, Linux, macOS, Android, and iOS.

Loop Mode Property

Loop Property

Enables or disables automatic loop playback.

// Enable loop mode
mediaPlayer.Loop = true;

// Disable loop mode
mediaPlayer.Loop = false;

Default value: false

Behavior: - When enabled, playback automatically restarts when end-of-stream (EOS) is reached - The underlying MediaBlocksPipeline handles the loop logic - The OnLoop event fires each time playback restarts - Seamlessly restarts playback without seeking overhead

Position Range Properties

Segment_Start Property

Sets the start position for segment playback.

// Start playback at 45 seconds
mediaPlayer.Segment_Start = TimeSpan.FromSeconds(45);

// Start playback at 3 minutes
mediaPlayer.Segment_Start = TimeSpan.FromMinutes(3);

Type: TimeSpan

Default value: TimeSpan.Zero

Behavior: - Defines where playback should begin - The player automatically seeks to this position when starting - Used in combination with Segment_Stop to define playback range - Applied through the underlying MediaBlocksPipeline.StartPosition property

Segment_Stop Property

Sets the end position for segment playback.

// Stop playback at 2 minutes
mediaPlayer.Segment_Stop = TimeSpan.FromMinutes(2);

// Play to the end (no stop position)
mediaPlayer.Segment_Stop = TimeSpan.Zero;

Type: TimeSpan

Default value: TimeSpan.Zero

Behavior: - Defines where playback should end - When playback reaches this position, end-of-stream (EOS) is triggered - If Loop is enabled, playback restarts from Segment_Start - Use TimeSpan.Zero for no stop position (play to end) - Applied through the underlying MediaBlocksPipeline.StopPosition property

MediaPlayerCoreX Events

OnLoop Event

Fires each time playback restarts in loop mode.

mediaPlayer.OnLoop += (sender, e) =>
{
    Console.WriteLine("Playback looped!");
};

When it fires: - Only when Loop property is true - When end-of-stream (EOS) is reached - Before playback restarts

Code Examples for MediaPlayerCoreX

Example 1: Basic Loop Mode

using VisioForge.Core.MediaPlayerX;
using VisioForge.Core.Types.X.Sources;

// Create media player instance
var player = new MediaPlayerCoreX();

// Enable loop mode
player.Loop = true;

// Subscribe to loop event
player.OnLoop += (sender, e) =>
{
    Console.WriteLine($"Loop iteration at {DateTime.Now}");
};

// Set source and play
var source = new UniversalSourceSettings()
{
    URI = new Uri(@"C:\Videos\sample.mp4")
};

await player.OpenAsync(source);
await player.PlayAsync();

Example 2: Play Specific Segment

using VisioForge.Core.MediaPlayerX;
using VisioForge.Core.Types.X.Sources;

var player = new MediaPlayerCoreX();

// Set segment range: play from 30s to 90s
player.Segment_Start = TimeSpan.FromSeconds(30);
player.Segment_Stop = TimeSpan.FromSeconds(90);

var source = new UniversalSourceSettings()
{
    URI = new Uri(@"C:\Videos\long-video.mp4")
};

await player.OpenAsync(source);
await player.PlayAsync();

Example 3: Loop Specific Segment

using VisioForge.Core.MediaPlayerX;
using VisioForge.Core.Types.X.Sources;

var player = new MediaPlayerCoreX();

// Enable loop and set segment
player.Loop = true;
player.Segment_Start = TimeSpan.FromMinutes(1);
player.Segment_Stop = TimeSpan.FromMinutes(2);

// Track loop count
int loopCount = 0;
player.OnLoop += (sender, e) =>
{
    loopCount++;
    Console.WriteLine($"Segment loop #{loopCount}");
};

var source = new UniversalSourceSettings()
{
    URI = new Uri(@"C:\Videos\video.mp4")
};

await player.OpenAsync(source);
await player.PlayAsync();

Example 4: Cross-Platform Looping Video

using VisioForge.Core.MediaPlayerX;
using VisioForge.Core.Types.X.Sources;

var player = new MediaPlayerCoreX();

// Enable seamless loop
player.Loop = true;

// For cross-platform video file path
string videoPath;
#if ANDROID
    videoPath = "/storage/emulated/0/Movies/background.mp4";
#elif IOS
    videoPath = Path.Combine(NSBundle.MainBundle.BundlePath, "background.mp4");
#else
    videoPath = Path.Combine(Environment.GetFolderPath(
        Environment.SpecialFolder.MyVideos), "background.mp4");
#endif

var source = new UniversalSourceSettings()
{
    URI = new Uri(videoPath)
};

await player.OpenAsync(source);
await player.PlayAsync();

Example 5: Segment Preview with UI Update

using VisioForge.Core.MediaPlayerX;
using VisioForge.Core.Types.X.Sources;

var player = new MediaPlayerCoreX();

// Preview mode: show 10 second clips
TimeSpan clipDuration = TimeSpan.FromSeconds(10);

async Task PreviewSegment(TimeSpan startTime)
{
    player.Segment_Start = startTime;
    player.Segment_Stop = startTime + clipDuration;

    // Seek to start position
    await player.Position_SetAsync(startTime);

    Console.WriteLine($"Previewing segment: {startTime} to {startTime + clipDuration}");
}

var source = new UniversalSourceSettings()
{
    URI = new Uri(@"C:\Videos\movie.mp4")
};

await player.OpenAsync(source);
await player.PlayAsync();

// Preview first segment
await PreviewSegment(TimeSpan.FromSeconds(0));

// Preview segment starting at 30 seconds
await Task.Delay(11000);
await PreviewSegment(TimeSpan.FromSeconds(30));

Example 6: Loop with Pause-on-Stop

using VisioForge.Core.MediaPlayerX;
using VisioForge.Core.Types.X.Sources;

var player = new MediaPlayerCoreX();

// Loop mode with pause instead of stop at end
player.Loop = true;
player.PauseOnStop = true; // Pause instead of stop at EOS

player.OnLoop += (sender, e) =>
{
    Console.WriteLine("Reached end, pausing briefly before loop...");

    // Wait before resuming (if needed)
    Task.Delay(1000).ContinueWith(_ => 
    {
        // Playback will restart automatically due to Loop = true
    });
};

var source = new UniversalSourceSettings()
{
    URI = new Uri(@"C:\Videos\video.mp4")
};

await player.OpenAsync(source);
await player.PlayAsync();

Best Practices

Performance Considerations

  1. Seamless Looping (MediaPlayerCore):
  2. Use Loop_DoNotSeekToBeginning = true for seamless loops without visual glitches
  3. Test with your specific media format for best results

  4. Short Segments:

  5. For very short segments (< 1 second), ensure media is properly indexed
  6. Some formats may not support frame-accurate seeking

  7. Cross-Platform (MediaPlayerCoreX):

  8. Test on all target platforms as GStreamer behavior may vary slightly
  9. Use appropriate video codecs that support seeking (H.264, H.265)

Common Use Cases

Kiosk Video Loop

// MediaPlayerCore (Windows)
player.Loop = true;
player.Loop_DoNotSeekToBeginning = true;

// MediaPlayerCoreX (Cross-platform)
player.Loop = true;

Preview Window

// MediaPlayerCore
player.Selection_Active = true;
player.Selection_Start = previewStart;
player.Selection_Stop = previewEnd;

// MediaPlayerCoreX
player.Segment_Start = previewStart;
player.Segment_Stop = previewEnd;

Continuous Segment Loop

// MediaPlayerCore
player.Loop = true;
player.Selection_Active = true;
player.Selection_Start = segmentStart;
player.Selection_Stop = segmentEnd;

// MediaPlayerCoreX
player.Loop = true;
player.Segment_Start = segmentStart;
player.Segment_Stop = segmentEnd;

Troubleshooting

Loop Not Working

MediaPlayerCore: - Ensure Loop property is set before calling PlayAsync() - Check that OnStop event is not calling Stop() method - Verify media file is not corrupted

MediaPlayerCoreX: - Ensure Loop property is set before calling PlayAsync() - Check GStreamer is properly initialized - Verify the pipeline is not being disposed prematurely

Position Range Not Accurate

MediaPlayerCore: - Ensure Selection_Active is set to true - Verify Selection_Start < Selection_Stop - Some media formats may not support frame-accurate seeking

MediaPlayerCoreX: - Verify Segment_Start and Segment_Stop are valid - Use seekable media formats (MP4, MKV with proper indexing) - Check that the media file supports seeking (not all streaming sources do)

Segment Playback Starts at Wrong Position

Both Engines: - Ensure positions are set before calling PlayAsync() - Wait for media to be fully loaded before setting positions - Use keyframe-based seeking for better accuracy

Property Comparison Table

Feature MediaPlayerCore MediaPlayerCoreX
Loop Mode Loop (bool) Loop (bool)
Seamless Loop Loop_DoNotSeekToBeginning (bool) Built-in (no extra property)
Range Active Selection_Active (bool) Implicit (when Segment properties set)
Start Position Selection_Start (TimeSpan) Segment_Start (TimeSpan)
Stop Position Selection_Stop (TimeSpan) Segment_Stop (TimeSpan)
Loop Event OnLoop OnLoop
Platform Windows only Cross-platform
Engine DirectShow GStreamer

Frequently Asked Questions

How do I create a seamless video loop without glitches in C#?

For the DirectShow engine (MediaPlayerCore), set Loop = true and Loop_DoNotSeekToBeginning = true to avoid a visible seek-back between iterations. For the cross-platform GStreamer engine (MediaPlayerCoreX), seamless restart is built in — simply set Loop = true. In both cases, use well-indexed formats like MP4 with H.264 or H.265 encoding for the smoothest transitions.

Does the Media Player SDK support frame-accurate seeking for segment playback?

Seeking accuracy depends on the media container and codec. MP4 and MKV files with proper keyframe indexing provide the best results. For very short segments (under one second), the player may land on the nearest keyframe rather than the exact requested position. If frame-level precision is critical, encode your source with a short GOP (Group of Pictures) length to increase keyframe density.

Can I loop a specific time range instead of the entire video file?

Yes. In MediaPlayerCore, enable Loop and Selection_Active, then set Selection_Start and Selection_Stop to define the segment. In MediaPlayerCoreX, enable Loop and set Segment_Start and Segment_Stop. The player will continuously repeat only the specified range. See the "Loop Specific Segment" code examples above for both engines.

See Also