From f87fdfee3c5d778093f410ae3791d9d23c439934 Mon Sep 17 00:00:00 2001 From: Alan Jeffrey Date: Thu, 30 Jul 2020 13:29:30 -0500 Subject: [PATCH 1/3] Add a prefs property to the gstreamer plugin --- ports/gstplugin/servowebsrc.rs | 47 ++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/ports/gstplugin/servowebsrc.rs b/ports/gstplugin/servowebsrc.rs index 6302131e163..4906d3875c4 100644 --- a/ports/gstplugin/servowebsrc.rs +++ b/ports/gstplugin/servowebsrc.rs @@ -75,6 +75,9 @@ use servo::compositing::windowing::WindowMethods; use servo::embedder_traits::EmbedderProxy; use servo::embedder_traits::EventLoopWaker; use servo::msg::constellation_msg::TopLevelBrowsingContextId; +use servo::servo_config::prefs::add_user_prefs; +use servo::servo_config::prefs::read_prefs_map; +use servo::servo_config::prefs::PrefValue; use servo::servo_config::set_pref; use servo::servo_url::ServoUrl; use servo::webrender_api::units::DevicePixel; @@ -115,6 +118,7 @@ pub struct ServoWebSrc { sender: Sender, url: Mutex>, webxr_mode: Mutex>, + prefs: Mutex>, outcaps: Mutex>, info: Mutex>, buffer_pool: Mutex>, @@ -172,6 +176,7 @@ enum ServoWebSrcMsg { ConnectionWhichImplementsDebug, ServoUrl, Option, + HashMap, Size2D, ), GetSwapChain(Sender>), @@ -195,13 +200,16 @@ struct ServoThread { impl ServoThread { fn new(sender: Sender, receiver: Receiver) -> Self { - let (connection, url, webxr_mode, size) = match receiver.recv() { - Ok(ServoWebSrcMsg::Start(connection, url, webxr_mode, size)) => { - (connection.0, url, webxr_mode, size) + let (connection, url, webxr_mode, prefs, size) = match receiver.recv() { + Ok(ServoWebSrcMsg::Start(connection, url, webxr_mode, prefs, size)) => { + (connection.0, url, webxr_mode, prefs, size) }, e => panic!("Failed to start ({:?})", e), }; - info!("Created new servo thread for {} ({:?})", url, webxr_mode); + info!( + "Created new servo thread for {} ({:?}, {:?})", + url, webxr_mode, prefs + ); let window = Rc::new(ServoWebSrcWindow::new(connection, webxr_mode, sender, size)); let embedder = Box::new(ServoWebSrcEmbedder::new(&window)); let webrender_swap_chain = window @@ -224,6 +232,8 @@ impl ServoThread { }, }; + add_user_prefs(prefs); + Self { receiver, servo, @@ -443,7 +453,16 @@ impl WebXRWindow for ServoWebSrcWebXR { } } -static PROPERTIES: [Property; 2] = [ +static PROPERTIES: [Property; 3] = [ + Property("prefs", |name| { + ParamSpec::string( + name, + "prefs", + "Servo preferences", + None, + glib::ParamFlags::READWRITE, + ) + }), Property("url", |name| { ParamSpec::string( name, @@ -485,6 +504,7 @@ impl ObjectSubclass for ServoWebSrc { let info = Mutex::new(None); let outcaps = Mutex::new(None); let url = Mutex::new(None); + let prefs = Mutex::new(None); let webxr_mode = Mutex::new(None); let buffer_pool = Mutex::new(None); let gl_context = Mutex::new(None); @@ -497,6 +517,7 @@ impl ObjectSubclass for ServoWebSrc { info, outcaps, url, + prefs, webxr_mode, buffer_pool, gl_context, @@ -539,6 +560,11 @@ impl ObjectImpl for ServoWebSrc { fn set_property(&self, _obj: &Object, id: usize, value: &Value) { let prop = &PROPERTIES[id]; match *prop { + Property("prefs", ..) => { + let mut guard = self.prefs.lock().expect("Failed to lock mutex"); + let prefs = value.get().expect("Failed to get prefs value"); + *guard = prefs; + }, Property("url", ..) => { let mut guard = self.url.lock().expect("Failed to lock mutex"); let url = value.get().expect("Failed to get url value"); @@ -564,6 +590,10 @@ impl ObjectImpl for ServoWebSrc { fn get_property(&self, _obj: &Object, id: usize) -> Result { let prop = &PROPERTIES[id]; match *prop { + Property("prefs", ..) => { + let guard = self.url.lock().expect("Failed to lock mutex"); + Ok(Value::from(guard.as_ref())) + }, Property("url", ..) => { let guard = self.url.lock().expect("Failed to lock mutex"); Ok(Value::from(guard.as_ref())) @@ -761,6 +791,12 @@ impl ServoWebSrc { error!("Failed to parse url {} ({:?})", url_string, e); FlowError::Error })?; + let prefs_guard = self.prefs.lock().expect("Poisoned mutex"); + let prefs_string = prefs_guard.as_ref().map(|s| &**s).unwrap_or("{}"); + let prefs = read_prefs_map(prefs_string).map_err(|e| { + error!("Failed to parse prefs {} ({:?})", prefs_string, e); + FlowError::Error + })?; let size = self .info .lock() @@ -773,6 +809,7 @@ impl ServoWebSrc { ConnectionWhichImplementsDebug(connection), url, webxr_mode, + prefs, size, )); From 78c76211774f473762164c95f0730b30e6d5a57d Mon Sep 17 00:00:00 2001 From: Alan Jeffrey Date: Thu, 30 Jul 2020 13:30:21 -0500 Subject: [PATCH 2/3] Add an example streaming a Hubs room to the gstreamer plugin --- ports/gstplugin/README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ports/gstplugin/README.md b/ports/gstplugin/README.md index 127c5a41639..2e6f87ac8de 100644 --- a/ports/gstplugin/README.md +++ b/ports/gstplugin/README.md @@ -91,6 +91,23 @@ GST_PLUGIN_PATH=target/gstplugins \ 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 and save to a file (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 \ + ! mp4mux \ + ! filesink location=test.mp4 +``` + *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. From 172d296c8be3207d84be4422ab1f0a87a3286017 Mon Sep 17 00:00:00 2001 From: Alan Jeffrey Date: Thu, 30 Jul 2020 13:31:12 -0500 Subject: [PATCH 3/3] Replace a bounded channel by an unbounded one in the gstreamer plugin --- ports/gstplugin/servowebsrc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/gstplugin/servowebsrc.rs b/ports/gstplugin/servowebsrc.rs index 4906d3875c4..4a8e8291b00 100644 --- a/ports/gstplugin/servowebsrc.rs +++ b/ports/gstplugin/servowebsrc.rs @@ -962,7 +962,7 @@ impl ServoWebSrc { if gfx.swap_chain.is_none() { debug!("Getting the swap chain"); - let (acks, ackr) = crossbeam_channel::bounded(1); + let (acks, ackr) = crossbeam_channel::unbounded(); let _ = self.sender.send(ServoWebSrcMsg::GetSwapChain(acks)); gfx.swap_chain = ackr.recv_timeout(Duration::from_millis(16)).ok(); }