servo/ports/gstplugin
Samson c0bee7cb86
Format toml files (#30112)
* Add taplo fmt config for toml fmt

* fmt toml files

* Add even-better-toml to extensions recommendations
2023-08-17 15:07:43 +00:00
..
build.rs Add a gstreamer servosrc plugin 2019-11-25 10:12:05 -06:00
Cargo.toml Format toml files (#30112) 2023-08-17 15:07:43 +00:00
lib.rs Rename servosrc to servowebsrc 2019-12-11 09:47:53 -06:00
logging.rs Miscellaneous gstreamer plugin fixes 2019-12-18 14:06:41 -06:00
README.md Fix typo in gstplugin readme.md 2020-11-22 13:16:43 +08:00
resources.rs Clean up some unused code after switching to rustls (#30081) 2023-08-09 01:02:02 +00:00
servowebsrc.rs Remove dependency on surfman-chains (#30090) 2023-08-11 14:24:10 +00:00
test.html Get the servosrc gstreamer plugin to use a GL buffer pool 2019-12-06 17:31:20 -06:00

A GStreamer plugin which runs servo

Supported platforms

  • MacOS + CGL
  • Linux + Wayland

Build

./mach build -r -p servo-gst-plugin

Install

By default, gstreamer's plugin finder will complain about any libraries it finds that aren't gstreamer plugins, so we need to have a directory just for plugins:

mkdir target/gstplugins

To install:

cp target/release/libgstservoplugin.* target/gstplugins

Run

To run locally:

GST_PLUGIN_PATH=target/gstplugins \
  gst-launch-1.0 -e servowebsrc \
    ! video/x-raw\(memory:GLMemory\),framerate=50/1,width=1920,height=1080,format=RGBA \
    ! glimagesink rotate-method=vertical-flip

To stream over the network:

GST_PLUGIN_PATH=target/gstplugins \
  gst-launch-1.0 -e servowebsrc \
    ! video/x-raw\(memory:GLMemory\),framerate=50/1,width=512,height=256 \
    ! glvideoflip video-direction=vert \
    ! glcolorconvert \
    ! gldownload \
    ! theoraenc \
    ! oggmux \
    ! tcpserversink host=127.0.0.1 port=8080

To stream to youtube live, first go to youtube studio and create a new live stream, with its token, then:

GST_PLUGIN_PATH=target/gstplugins \
  gst-launch-1.0 -e servowebsrc \
    ! video/x-raw\(memory:GLMemory\),framerate=50/1,width=1960,height=1080 \
    ! glvideoflip video-direction=vert \
    ! glcolorconvert \
    ! gldownload \
    ! x264enc bitrate=6000 \
    ! flvmux name=mux \
    ! rtmpsink location="rtmp://a.rtmp.youtube.com/live2/x/$TOKEN" \
    audiotestsrc wave=silence \
    ! voaacenc bitrate=128000 \
    ! mux.

To save to a file:

GST_PLUGIN_PATH=target/gstplugins \
  gst-launch-1.0 -e servowebsrc \
    ! video/x-raw\(memory:GLMemory\),framerate=50/1,width=512,height=256 \
    ! glvideoflip video-direction=vert \
    ! glcolorconvert \
    ! gldownload \
    ! theoraenc \
    ! oggmux \
    ! filesink location=test.ogg

To stream webxr content and save to a file:

GST_PLUGIN_PATH=target/gstplugins \
 gst-launch-1.0 -e servowebsrc url=... webxr=left-right \
   ! video/x-raw\(memory:GLMemory\),framerate=50/1,width=512,height=512,format=RGBA \
   ! glvideoflip video-direction=vert \
   ! glcolorconvert \
   ! gldownload \
   ! queue \
   ! x264enc \
   ! mp4mux \
   ! filesink location=test.mp4

This requires the webxr content to support the sessionavailable event for launching directly into immersive mode. Values for webxr include none, left-right, red-cyan, cubemap and spherical.

To stream a Hubs room to twitch (there'll be ~30s black at the beginning while Hubs starts up):

GST_PLUGIN_PATH=$PWD/target/gstplugins \
  gst-launch-1.0 -e servowebsrc \
      url="https://hubs.mozilla.com/$ROOM?no_force_webvr&vr_entry_type=vr_now" \
      webxr=red-cyan \
      prefs='{"dom.gamepad.enabled":true, "dom.svg.enabled":true, "dom.canvas_capture.enabled": true, "dom.canvas_capture.enabled":true, "dom.webrtc.enabled":true, "dom.webrtc.transceiver.enabled":true}' \
    ! video/x-raw\(memory:GLMemory\),framerate=50/1,width=1920,height=1080,format=RGBA \
    ! glvideoflip video-direction=vert \
    ! glcolorconvert \
    ! gldownload \
    ! queue \
    ! x264enc bitrate=4500 \
    ! video/x-h264, profile=high \
    ! flvmux streamable=true \
    ! rtmpsink location="rtmp://$ENDPOINT.twitch.tv/app/$STREAM_KEY"

Note: killing the gstreamer pipeline with control-C sometimes locks up macOS to the point of needing a power cycle. Killing the pipeline by closing the window seems to work.

Troubleshooting building the plugin

You may need to make sure rust picks up the right gstreamer, for example:

PKG_CONFIG_PATH=$PWD/support/linux/gstreamer/gst/lib \
LD_LIBRARY_PATH=$PWD/support/linux/gstreamer/gst/lib \
  ./mach build -r -p servo-gst-plugin

Troubleshooting running the plugin

First try:

GST_PLUGIN_PATH=target/gstplugins \
  gst-inspect-1.0 servowebsrc

If that doesn't work, try:

GST_PLUGIN_PATH=target/gstplugins \
  gst-inspect-1.0 target/gstplugins/libgstservoplugin.so

If you get reports about the plugin being blacklisted, remove the (global!) gstreamer cache, e.g. under Linux:

rm -r ~/.cache/gstreamer-1.0

If you get complaints about not being able to find libraries, set LD_LIBRARY_PATH, e.g. to use Servo's Linux gstreamer:

LD_LIBRARY_PATH=$PWD/support/linux/gstreamer/gst/lib

If you get complaints cannot allocate memory in static TLS block this is caused by gstreamer initializing threads using the system alloc, which causes problems if those threads run Rust code that uses jemalloc. The fix is to preload the plugin:

LD_PRELOAD=$PWD/target/gstplugins/libgstservoplugin.so

You may need to set GST_PLUGIN_SCANNER, e.g. to use Servo's:

GST_PLUGIN_SCANNER=$PWD/support/linux/gstreamer/gst/libexec/gstreamer-1.0/gst-plugin-scanner

You may need to include other directories on the plugin search path, e.g. Servo's gstreamer:

GST_PLUGIN_PATH=$PWD/target/gstplugins/:$PWD/support/linux/gstreamer/gst/lib

If you get complaints could not get/set settings from/on resource. right after finding a GL context then try tee-ing to glimagesink and gldownload:

LD_PRELOAD=$PWD/target/gstplugins/libgstservoplugin.so \
GST_PLUGIN_PATH=target/gstplugins \
  gst-launch-1.0 servowebsrc \
    ! video/x-raw\(memory:GLMemory\),framerate=50/1,width=512,height=256 \
    !  tee name=t \
 t. ! queue ! glimagesink 
 t. ! queue ! glcolorconvert ! gldownload ! theoraenc ! oggmux ! filesink location=test.ogg

Under X11 you may get complaints about X11 threads not being initialized:

GST_GL_XINITTHREADS=1

Under x11 you may get a frozen display from autovideosink, try ximagesink instead.

Putting that all together:

GST_GL_XINITTHREADS=1 \
GST_PLUGIN_PATH=$PWD/target/gstplugins/:$PWD/support/linux/gstreamer/gst/lib \
GST_PLUGIN_SCANNER=$PWD/support/linux/gstreamer/gst/libexec/gstreamer-1.0/gst-plugin-scanner \
LD_LIBRARY_PATH=$PWD/support/linux/gstreamer/gst/lib \
LD_PRELOAD=$PWD/target/gstplugins/libgstservoplugin.so \
  gst-launch-1.0 servowebsrc \
    ! videoflip video-direction=vert \
    ! ximagesink