-
Notifications
You must be signed in to change notification settings - Fork 2
Implementing Video Receiver Pipelines
For general information about receiver pipelines refer to the Receiver Pipelines section section.
This document describes a video processing pipeline designed to handle network-streamed video data efficiently by applying various transformations to optimize visual quality and reduce network and computational load. The ssdk::video::MonoscopicVideoInput and ssdk::video::VideoReceiverPipeline components, combined with the processing slots, provide a flexible infrastructure to handle format changes, enhance quality, and manage resolution.
Platform Scope The concepts described in this document (multi-stage pipelines, presenters, and AMF components chained via slots) fully apply to Windows and Linux. On Android, video presentation is handled differently: the decoder renders directly into a view surface and there is no traditional multi-stage post-processing pipeline. Platform-specific differences are called out where relevant.
Video data is obtained from the ssdk::transport_common::ClientTransport interface and relayed to the ssdk::video::VideoDispatcher object through the transport_common::ClientTransport::VideoReceiverCallback. The ssdk::video::VideoDispatcher object is responsible for routing various video streams to their respective video inputs, represented by the ssdk::video::MonoscopicVideoInput class. Upon receiving the video buffers, ssdk::video::MonoscopicVideoInput decodes compressed video frames and forwards the decoded frames to the ssdk::video::VideoReceiverPipeline-based objects.
On Windows and Linux, the decoded frames are then passed through a chain of AMF components and finally presented using a dedicated presenter component. On Android, the decoder targets a view surface directly, and only frame metadata is propagated through the pipeline abstraction.
ssdk::video::VideoReceiverPipeline provides the common, platform-agnostic base for receive-side video processing. It owns the basic slot infrastructure and exposes methods such as:
-
SubmitInput()– entry point for decoded frames or pass-through surfaces. -
OnInputChanged()– reinitializes internal state when input format changes (codec, resolution, frame rate, color space, etc.). -
Shutdown()/ lifecycle helpers – to tear down pipeline resources.
Platform-specific implementations extend this base as follows:
-
Windows and Linux:
ssdk::video::VideoReceiverPipelinePCderives fromVideoReceiverPipelineand implements a full multi-stage pipeline, including optional denoiser, high-quality upscaler, and color-space / format conversion, with a video presenter used as the final sink. -
Android:
ssdk::video::VideoReceiverAndroid(located insdk/video/android) adapts the same base concepts but does not build a traditional multi-stage GPU pipeline. Instead, it configures the decoder to output directly to a platform-specific view surface (e.g., a Surface/SurfaceView/TextureView), and uses the pipeline infrastructure only to propagate timing and metadata.
On Windows and Linux, once decoded or passed through, video data is submitted to the processing pipeline using the VideoReceiverPipeline::SubmitInput() method. The pipeline consists of a series of slots, each containing an amf::AMFComponent object.
The slots can be implemented as either synchronous or asynchronous, based on the component’s processing characteristics:
-
Synchronous Slots (
ssdk::util::SynchronousSlot): ExecutesSubmitInputandQueryOutputin a single thread. This approach is compatible with components that produce a matching output frame for every input frame. -
Asynchronous Slots (
ssdk::util::AsynchronousSlot): ExecutesSubmitInputandQueryOutputin separate threads, ideal for high-complexity components with varied input-output ratios.
In VideoReceiverPipelinePC, the following key components are typically chained together, each serving a distinct purpose in video enhancement, resolution handling, and color space conversion:
This component, implemented using the AMFVQEnhancer in the AMF runtime, improves visual clarity by removing noise and compression artifacts from the video. It enables rendering and streaming at lower resolutions and bitrates, reducing the load on the network and encoding/decoding resources while enhancing quality.
- Performance Benefits: By reducing required bitrate and resolution, this component improves streaming efficiency and reduces bandwidth.
- Hardware Requirements: Available only on Windows systems with AMD GPUs/APUs.
- Performance Considerations: This process is computationally intensive, especially on lower-end GPUs, and can be a bottleneck at high resolutions or frame rates.
The AMFHQScaler component provides advanced upscaling for scenarios where the stream resolution is lower than the display resolution. This upscaling is applied only when necessary.
- Performance Benefits: Allows video streaming at a reduced resolution, with high-quality upscaling on the client side, optimizing both network and GPU resource usage.
- Hardware Requirements: Available only on Windows systems with AMD GPUs/APUs.
- Performance Considerations: Like the denoiser, this component is computationally heavy, potentially causing bottlenecks on lower-end GPUs with high resolutions or frame rates.
The Video Converter performs essential color space conversion and can also perform resolution scaling (either upscaling or downscaling) when required. This component operates as follows:
- Color Space Conversion: Converts the YUV format output by the decoder to the RGB format required by the presenter.
- Scaling: Uses bilinear or bicubic scalers but defers scaling to the presenter itself when the high-performance upscaler is not being used. This approach maintains performance by only applying essential conversions within the pipeline.
When a format change occurs in the video stream (e.g., codec, resolution, frame rate, color space), MonoscopicVideoInput invokes VideoReceiverPipeline::OnInputChanged() to reinitialize pipeline components for compatibility with the new format. The base class takes care of common state management, while VideoReceiverPipelinePC and VideoReceiverAndroid perform any platform-specific reconfiguration (for example, re-creating the presenter chain on PC or updating the decoder / surface configuration on Android).
On PC platforms, the video pipeline, which sits between MonoscopicVideoInput and the video presenter, processes video as follows:
-
Input Handling:
MonoscopicVideoInputsubmits decoded frames toVideoReceiverPipeline::SubmitInput(). -
Sequential Processing:
VideoReceiverPipelinePCpushes each frame through the configured slots (denoiser, upscaler, converter, and any additional components) depending on the stream’s resolution, display requirements, and available hardware. - Synchronous and Asynchronous Execution: Each component is evaluated to determine whether synchronous or asynchronous execution is optimal.
- Final Output: The presenter receives frames for display, with resolution and color matching as required.
To optimize performance on Windows and Linux, consider the following:
- Denoiser and Upscaler on Capable Hardware: Ensure these components are executed asynchronously if they require heavy processing, especially at high resolutions.
- Experiment with Slot Type: For components with stable input-output behavior, synchronous slots may perform best; otherwise, asynchronous slots provide flexibility and responsiveness for components with dynamic output requirements.
This structure allows the video pipeline to adapt to different hardware and network conditions, providing a high-quality streaming experience on AMD GPUs while efficiently managing computational and network resources on PC, while Android uses a simplified, surface-based presentation model backed by the same base VideoReceiverPipeline infrastructure for timing and control.
On Android, there is no separate video presenter component in the Streaming SDK pipeline. Instead:
- The video decoder is configured to output directly to a platform-specific view surface owned by the Android UI layer.
- There is effectively no multi-stage GPU post-processing pipeline equivalent to the Windows/Linux implementation.
- The decoder component still implements
amf::AMFComponent::QueryOutput(), but on Android it only returns anamf::AMFPropertyStorageobject containing per-frame metadata (such as presentation timestamps and other properties). -
VideoReceiverAndroiduses this metadata primarily for audio/video synchronization, passing timing information to thessdk::util::AVSynchronizerand related components, while the actual pixel presentation is handled by the Android view hierarchy.
This design keeps the synchronization model consistent across platforms while letting Android rely on its native presentation stack.