Table of Contents

Publishing Point with Proxy Source

This use-case demonstrates how to pull a stream from a remote source and forcibly transcode it before redistribution. The ProxySource wraps an existing IMediaSource and applies per-stream transcoding — decoding the original media and re-encoding it with user-specified codec parameters.

Overview

The createProxySource() method performs the following:

  1. Creates a media source from a remote URI using SourceFactory
  2. Waits for the source to open asynchronously
  3. Wraps the source in a ProxySource
  4. Iterates over all streams and configures the desired output codec for each
  5. Creates the publishing point with the proxy source

When to Use ProxySource

A pull source passes compressed data through to clients without modification. Use ProxySource when you need to:

  • Re-encode video to a different codec, bitrate, or profile (e.g., enforce H.264 Constrained Baseline for maximum compatibility)
  • Normalize audio to a standard format (e.g., always output AAC regardless of the source codec)
  • Change resolution, framerate, or keyframe interval

Creating the Original Source

VAST.Media.IMediaSource originalSource = VAST.Media.SourceFactory.Create(uri);

SourceFactory creates the appropriate source type based on the URI protocol (rtsp://, rtmp://, srt://, etc.). The source opens asynchronously — StateChanged events indicate when it is ready.

Waiting for the Source to Open

originalSource.StateChanged += (object sender, Media.MediaState e) =>
{
    switch (e)
    {
        case VAST.Media.MediaState.Opened:
        {
            // source is ready — create proxy and publishing point
            break;
        }

        case VAST.Media.MediaState.Error:
        {
            // handle connection error
            break;
        }
    }
};

originalSource.Open();

The Open() call initiates the connection. Once the source enters the Opened state, its stream count and media types are available and the proxy can be created.

Creating the Proxy Source

var proxySource = new VAST.Media.ProxySource(originalSource);
proxySource.Open();

ProxySource wraps the original source. When Open() is called on a proxy whose original source is already opened, it completes synchronously.

Configuring Output Types

After opening, iterate over all streams and set the desired output type for each:

for (int i = 0; i < proxySource.StreamCount; ++i)
{
    VAST.Common.MediaType inputMediaType = proxySource.GetMediaType(i);
    switch (inputMediaType.ContentType)
    {
        case VAST.Common.ContentType.Audio:
            proxySource.SetDesiredOutputType(i, new VAST.Common.MediaType
            {
                ContentType = VAST.Common.ContentType.Audio,
                CodecId = VAST.Common.Codec.AAC,
                Bitrate = 128000,
                SampleRate = 44100,
                Channels = 2,
            }).Wait();
            break;

        case VAST.Common.ContentType.Video:
            VAST.Common.MediaType outputMediaType = new VAST.Common.MediaType
            {
                ContentType = VAST.Common.ContentType.Video,
                CodecId = VAST.Common.Codec.H264,
                Bitrate = inputMediaType.Width * inputMediaType.Height * 3,
                Width = inputMediaType.Width,
                Height = inputMediaType.Height,
                Framerate = inputMediaType.Framerate,
            };
            outputMediaType.Metadata.Add("KeyframeInterval",
                ((int)Math.Ceiling(inputMediaType.Framerate.ToDouble())).ToString());
            outputMediaType.Metadata.Add("Profile", (0x100 | 66).ToString());
            proxySource.SetDesiredOutputType(i, outputMediaType).Wait();
            break;
    }
}

SetDesiredOutputType is asynchronous — it initializes the decoder and encoder for the stream. Once called, the proxy decodes incoming frames and re-encodes them to the specified output type.

Video Output

The sample preserves the original resolution and framerate, but re-encodes to H.264 with:

Parameter Value Description
Bitrate Width * Height * 3 Calculated from input dimensions
KeyframeInterval Framerate (rounded up) One keyframe per second
Profile 0x100 \| 66 H.264 Constrained Baseline profile

The KeyframeInterval and Profile are passed via the Metadata dictionary — these are encoder-specific hints that the encoding backend interprets.

Audio Output

Audio is normalized to AAC at 44.1 kHz stereo, 128 kbps, regardless of the source audio codec.

Creating the Publishing Point

this.server.CreatePublishingPoint(publishingPath, proxySource);

The sample is called with:

this.createProxySource("transcode", "rtsp://192.168.0.101/stream");

The transcoded stream is then available at rtsp://server/transcode, rtmp://server/live/transcode, http://server:8888/hls/transcode, etc.

See Also