Table of Contents

VAST.TS Library

The VAST.TS library provides MPEG-2 Transport Stream (TS) functionality for VASTreaming applications. It supports UDP multicast streaming, TS over HTTP delivery, and file-based operations including playback and recording with automatic file rotation.

MPEG-2 Transport Stream is widely used as the container format by various streaming protocols, including HLS, SRT, and RTP. The VAST.TS library provides the underlying TS muxing and demuxing capabilities used by these protocol implementations.

Overview

Feature Description
UDP Multicast Receive and send TS streams over UDP multicast
TS over HTTP Deliver TS streams to HTTP clients
File Playback Read and play TS files with seeking support
File Recording Write TS files with automatic file rotation
Format Parsing Full MPEG-2 TS demuxing and muxing

Requirements

Supported Codecs

Video Codecs

Codec Stream Type Notes
H.264/AVC 0x1B Full support with NAL unit handling
H.265/HEVC 0x24 Full support with NAL unit handling
MPEG-1 0x01 Standard MPEG-1 video
MPEG-2 0x02 Standard MPEG-2 video

Audio Codecs

Codec Stream Type Notes
AAC (ADTS) 0x0F MPEG-2 AAC audio
AAC (LATM) 0x11 MPEG-4 AAC audio
MP1 0x03/0x04 MPEG-1/2 Layer I
MP2 0x03/0x04 MPEG-1/2 Layer II
MP3 0x03/0x04 MPEG-1/2 Layer III
AC-3 0x81 Dolby Digital
E-AC-3 0x87 Enhanced AC-3

Data Streams

The TS muxer/demuxer includes custom support for text and binary data streams, enabling metadata passthrough via TS streaming or file storage.

Stream Type Content Type Description
Text Text/XML UTF-8 encoded text data (e.g., ONVIF metadata)
Binary Binary Raw binary data streams

This feature is useful for:

  • Passing ONVIF metadata alongside video/audio streams
  • Recording metadata to TS files for later retrieval
  • Streaming custom application data through TS infrastructure

UDP Multicast Source

The TsSource receives MPEG-2 Transport Streams over UDP multicast.

URI Format

udp://<multicast-ip>:<port>?vast-local-ip=<binding-ip>&vast-program-pid=<pid>
Parameter Description
multicast-ip Multicast group IP address
port UDP port number
vast-local-ip Optional local interface IP to bind to
vast-program-pid Optional program PID filter (decimal or hex with 0x prefix)

Usage

var source = new VAST.TS.TsSource();
source.Uri = "udp://239.0.0.1:1234";

source.NewStream += (sender, e) =>
{
    Console.WriteLine($"Stream {e.StreamIndex}: {e.MediaType.ContentType}");
};

source.NewSample += (sender, e) =>
{
    // Process received media sample
    ProcessSample(e.Sample);
};

source.StateChanged += (sender, state) =>
{
    if (state == MediaState.Opened)
    {
        source.Start();
    }
};

source.Open();

Program Filtering

When a transport stream contains multiple programs, use the vast-program-pid parameter to select a specific program:

// Select program with PMT PID 0x100
source.Uri = "udp://239.0.0.1:1234?vast-program-pid=0x100";

UDP Multicast Sink

The TsSink sends MPEG-2 Transport Streams over UDP multicast.

URI Format

udp://<multicast-ip>:<port>?vast-local-ip=<binding-ip>&vast-ttl=<ttl>&vast-mtu=<mtu>
Parameter Description
multicast-ip Multicast group IP address
port UDP port number
vast-local-ip Optional local interface IP to bind to
vast-ttl Optional time-to-live for multicast packets
vast-mtu Optional MTU size for packet combining

Usage

var sink = new VAST.TS.TsSink();
sink.Uri = "udp://239.0.0.1:1234?vast-ttl=32";

sink.AddStream(0, videoMediaType);
sink.AddStream(1, audioMediaType);

sink.StateChanged += (sender, state) =>
{
    if (state == MediaState.Opened)
    {
        sink.Start();
    }
};

sink.Open();

...

// Push media samples
sink.PushMedia(0, videoSample);
sink.PushMedia(1, audioSample);

sink.Stop();

MTU and Packet Combining

When vast-mtu is specified, the sink combines multiple TS packets into single UDP datagrams up to the MTU size for improved network efficiency:

// Combine packets up to 1316 bytes (7 TS packets)
sink.Uri = "udp://239.0.0.1:1234?vast-mtu=1316";

TS File Source

The TsFileSource reads MPEG-2 Transport Stream files with full interactive playback support.

Features

Feature Support
Seeking Frame-accurate seeking via keyframe index
Playback Rate Variable speed playback
Looping Continuous loop playback
Pause/Resume Full pause and resume support
Transcoding On-the-fly transcoding to user specified format

Usage

var source = new VAST.TS.TsFileSource();
source.Uri = "video.ts";

source.NewStream += (sender, e) =>
{
    Console.WriteLine($"Stream {e.StreamIndex}: {e.MediaType.ContentType}");
    Console.WriteLine($"Duration: {source.Duration}");
};

source.NewSample += (sender, e) =>
{
    ProcessSample(e.Sample);
};

source.StateChanged += (sender, state) =>
{
    if (state == MediaState.Opened)
    {
        source.Start();
    }
};

source.Open();

Seeking and Playback Control

// Seek to position
source.Position = TimeSpan.FromSeconds(30);

// Change playback rate
source.PlaybackRate = 2.0; // 2x speed

// Pause
source.Pause();

// Resume
source.Start();

Playback Rates

Rate Description
double.MinValue As fast as possible in backward direction (no pacing)
-32 to -1 Rewind (backward playback)
0 to 1 (exclusive) Slow motion
1 Normal speed
1 to 32 Fast forward
double.MaxValue As fast as possible (no pacing)

Loop Mode

Enable continuous looping for playlist-like behavior:

source.Loop = true;
source.Uri = "video.ts";
source.Open();
Note

When Loop is enabled, seeking and pause are not available.

Program PID Filtering

Select a specific program when the TS file contains multiple programs:

// Filter by program PID
var source = new VAST.TS.TsFileSource(programPid: 0x100);
source.Uri = "multi-program.ts";
source.Open();

On-the-fly Decoding

Request decoded output format for a stream:

source.StateChanged += async (sender, state) =>
{
    if (state == MediaState.Opened)
    {
        // Request decoded video output
        var decodedType = new MediaType
        {
            ContentType = ContentType.Video,
            CodecId = Codec.Uncompressed,
            PixelFormat = PixelFormat.NV12
        };

        await source.SetDesiredOutputType(0, decodedType);
        source.Start();
    }
};

TS File Sink

The TsFileSink writes MPEG-2 Transport Stream files with automatic file rotation support.

Usage

var sink = new VAST.TS.TsFileSink();
sink.Uri = "recording.ts";

sink.AddStream(0, videoMediaType);
sink.AddStream(1, audioMediaType);

sink.StateChanged += (sender, state) =>
{
    if (state == MediaState.Opened)
    {
        sink.Start();
    }
};

sink.Open();

...

// Push media samples
sink.PushMedia(0, videoSample);
sink.PushMedia(1, audioSample);

sink.Stop();

File Rotation

Automatically split recordings into multiple files:

var sink = new VAST.TS.TsFileSink();
sink.RotationPeriod = 3600; // Rotate every hour (seconds)

int fileNumber = 0;
sink.NextUri = () => $"recording_{fileNumber++:D4}.ts";

sink.UriRotated += (sender, e) =>
{
    Console.WriteLine($"Completed: {e.Uri}");
    Console.WriteLine($"Duration: {e.Finished - e.Started}");
};

sink.AddStream(0, videoMediaType);
sink.AddStream(1, audioMediaType);

sink.Open();

File rotation occurs at keyframes to ensure each file starts with a valid GOP.

Writing to Stream

Write TS data to a custom stream instead of a file:

var memoryStream = new MemoryStream();

var sink = new VAST.TS.TsFileSink();
sink.Stream = memoryStream;

sink.AddStream(0, videoMediaType);

sink.StateChanged += (sender, state) =>
{
    if (state == MediaState.Opened)
    {
        sink.Start();
    }
};

sink.Open();

...

sink.PushMedia(0, videoSample);

sink.Stop();

// Access the TS data
byte[] tsData = memoryStream.ToArray();

Delayed Start

Use delayed start when the first media sample may arrive after a significant delay:

sink.Start(delayedStart: true);

// File will be created/recreated when first sample arrives
// Empty file is automatically deleted if no samples received

TS over HTTP Server

The TS over HTTP server delivers Transport Streams to HTTP clients for browser-based playback and streaming applications.

Integration with StreamingServer

Note

TsHttpServer is not available as a standalone server. It operates as part of the VAST.Network.StreamingServer infrastructure and is instantiated by the StreamingServer automatically when enabled.

var server = new VAST.Network.StreamingServer();

// Enable TS over HTTP
server.EnableTsHttp = true;
server.TsHttpServerParameters = new VAST.TS.TsHttpServerParameters
{
    TsHttpPath = "/ts/"
};

server.Start();

Client Access

Clients connect via HTTP GET requests:

http://server:port/ts/stream-name

The server responds with a continuous TS stream using chunked transfer encoding.

Troubleshooting

Common Issues

Issue Cause Solution
No streams detected Invalid TS format Verify file/stream is valid MPEG-2 TS
Multicast not received Network/firewall issue Check multicast routing, firewall rules
Audio/video out of sync Timestamp discontinuity Check source for timestamp jumps
Seeking inaccurate Missing keyframe index Ensure file has regular keyframes
File rotation not working No keyframes Rotation occurs at keyframes only

Debugging

Enable debug logging to diagnose issues:

VAST.Common.Log.Level = VAST.Common.Log.LogLevel.Debug;

See Also