GStreamer
GStreamer is a library for constructing graphs of media-handling components. The applications it supports range from simple Ogg/Vorbis playback, audio/video streaming to complex audio (mixing) and video (non-linear editing) processing.
Overview
We implemented two custom plugins (one for video and one for audio) in order to turn a stream of bytes into a stream of valid Moonlight RTP packets.
This allows users to be able to compose Gstreamer pipelines in any form or shape and, near the end, plug our plugin so that it can be streamed to Moonlight.
The plugin
The basic flow is the following:
-
The plugin receives a
GstBuffer
of binary data: the encoded video or audio stream into a format that can be decoded back by the Moonlight client. -
We’ll split this into a
GstBufferList
of valid RTP packets following the Moonlight specifications; this includes:-
split the original buffer into a set of correctly sized chunks
-
Encrypt the chunks when enabled
-
add RTP headers to each chunk
-
create additional RTP packets with the FEC information
-
-
Push the resulting list downstream
This flow is general enough to enable us to use the same plugin for H.264, HEVC and AV1 (and any other encoder that will be supported in future). Downstream, it’s also trivial to switch between UDP/TCP or even a complete different delivery method if needed.
We decided to split between audio and video because they have different RTP packet structure, non overlapping properties, different FEC encoding and different encryption requirements but the basic flow is the same for both plugins.
Given that this is a direct transformation from one input buffer to another output buffer we decided to use GstBaseTransform as the base class.
This will implement some boilerplate code for us so that we can focus on the main _transform
virtual method implementation.
Following the nomenclature used in the official GStreamer RTP plugins we called them rtpmoonlightpay_video
and rtpmoonlightpay_audio
as in RTP Moonlight Payloader video/audio.
Code
GStreamer uses GObjects: a mechanism to retrofit Objects into C. I suggest you to get a bit familiar with it before diving into the code; here’s a great and simple tutorial.
Following the official docs at Plugin Write’s Guide we started off with the official bash script that creates the boilerplate code from the selected base class; namely:
-
gstrtpmoonlightpay_video.hpp and gstrtpmoonlightpay_video.cpp contain all the boilerplate code needed to setup a plugin, property definitions, etc.
-
gstrtpmoonlightpay_audio.hpp and gstrtpmoonlightpay_audio.cpp for audio.
-
-
video.hpp contains all the functions that turns a linear buffer of data into a list of correctly formed RTP packets.
-
audio.hpp same for audio
-