diff options
author | Fernando Jiménez Moreno <ferjmoreno@gmail.com> | 2019-11-07 17:35:10 +0100 |
---|---|---|
committer | Fernando Jiménez Moreno <ferjmoreno@gmail.com> | 2019-11-18 17:14:51 +0100 |
commit | a72e46f9c8c897ecff603899704e5b88484c1138 (patch) | |
tree | 54b4b73a581da4850f995d6efcae352adb98cb9f | |
parent | 03485d730ffc3b5c3b9e2c66c2d985c83ccb5665 (diff) | |
download | servo-a72e46f9c8c897ecff603899704e5b88484c1138.tar.gz servo-a72e46f9c8c897ecff603899704e5b88484c1138.zip |
MediaElementAudioSourceNode: set audio renderer
-rw-r--r-- | components/script/dom/bindings/trace.rs | 2 | ||||
-rw-r--r-- | components/script/dom/htmlmediaelement.rs | 27 | ||||
-rw-r--r-- | components/script/dom/mediaelementaudiosourcenode.rs | 8 |
3 files changed, 29 insertions, 8 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 301d8fe5390..74e6996b67a 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -107,6 +107,7 @@ use servo_media::audio::context::AudioContext; use servo_media::audio::graph::NodeId; use servo_media::audio::panner_node::{DistanceModel, PanningModel}; use servo_media::audio::param::ParamType; +use servo_media::player::audio::AudioRenderer; use servo_media::player::video::VideoFrame; use servo_media::player::Player; use servo_media::streams::registry::MediaStreamId; @@ -534,6 +535,7 @@ unsafe_no_jsmanaged_fields!(CascadeData); unsafe_no_jsmanaged_fields!(WindowGLContext); unsafe_no_jsmanaged_fields!(VideoFrame); unsafe_no_jsmanaged_fields!(WebGLContextId); +unsafe_no_jsmanaged_fields!(Arc<Mutex<dyn AudioRenderer>>); unsafe impl<'a> JSTraceable for &'a str { #[inline] diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index 53756a10576..d10801c5779 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -79,6 +79,7 @@ use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseLis use net_traits::{NetworkError, ResourceFetchTiming, ResourceTimingType}; use script_layout_interface::HTMLMediaData; use servo_config::pref; +use servo_media::player::audio::AudioRenderer; use servo_media::player::video::{VideoFrame, VideoFrameRenderer}; use servo_media::player::{PlaybackState, Player, PlayerError, PlayerEvent, SeekLock, StreamType}; use servo_media::{ClientContextId, ServoMedia, SupportsMediaType}; @@ -326,6 +327,8 @@ pub struct HTMLMediaElement { player: DomRefCell<Option<Arc<Mutex<dyn Player>>>>, #[ignore_malloc_size_of = "Arc"] video_renderer: Arc<Mutex<MediaFrameRenderer>>, + #[ignore_malloc_size_of = "Arc"] + audio_renderer: DomRefCell<Option<Arc<Mutex<dyn AudioRenderer>>>>, /// https://html.spec.whatwg.org/multipage/#show-poster-flag show_poster: Cell<bool>, /// https://html.spec.whatwg.org/multipage/#dom-media-duration @@ -413,6 +416,7 @@ impl HTMLMediaElement { video_renderer: Arc::new(Mutex::new(MediaFrameRenderer::new( document.window().get_webrender_api_sender(), ))), + audio_renderer: Default::default(), show_poster: Cell::new(true), duration: Cell::new(f64::NAN), playback_position: Cell::new(0.), @@ -1325,11 +1329,14 @@ impl HTMLMediaElement { let window = window_from_node(self); let (action_sender, action_receiver) = ipc::channel::<PlayerEvent>().unwrap(); - let renderer: Option<Arc<Mutex<dyn VideoFrameRenderer>>> = match self.media_type_id() { + let video_renderer: Option<Arc<Mutex<dyn VideoFrameRenderer>>> = match self.media_type_id() + { HTMLMediaElementTypeId::HTMLAudioElement => None, HTMLMediaElementTypeId::HTMLVideoElement => Some(self.video_renderer.clone()), }; + let audio_renderer = self.audio_renderer.borrow().as_ref().map(|r| r.clone()); + let pipeline_id = window .pipeline_id() .expect("Cannot create player outside of a pipeline"); @@ -1339,8 +1346,8 @@ impl HTMLMediaElement { &client_context_id, stream_type, action_sender, - renderer, - None, + video_renderer, + audio_renderer, Box::new(window.get_player_context()), ); @@ -1862,6 +1869,20 @@ impl HTMLMediaElement { None => return None, } } + + /// By default the audio is rendered through the audio sink automatically + /// selected by the servo-media Player instance. However, in some cases, like + /// the WebAudio MediaElementAudioSourceNode, we need to set a custom audio + /// renderer. + pub fn set_audio_renderer(&self, audio_renderer: Arc<Mutex<dyn AudioRenderer>>) { + *self.audio_renderer.borrow_mut() = Some(audio_renderer); + if let Some(ref player) = *self.player.borrow() { + if let Err(e) = player.lock().unwrap().stop() { + eprintln!("Could not stop player {:?}", e); + } + self.media_element_load_algorithm(); + } + } } // XXX Placeholder for [https://github.com/servo/servo/issues/22293] diff --git a/components/script/dom/mediaelementaudiosourcenode.rs b/components/script/dom/mediaelementaudiosourcenode.rs index 8ec25026bc1..312857569e6 100644 --- a/components/script/dom/mediaelementaudiosourcenode.rs +++ b/components/script/dom/mediaelementaudiosourcenode.rs @@ -26,7 +26,6 @@ pub struct MediaElementAudioSourceNode { impl MediaElementAudioSourceNode { #[allow(unrooted_must_root)] fn new_inherited( - window: &Window, context: &AudioContext, options: &MediaElementAudioSourceOptions, ) -> Fallible<MediaElementAudioSourceNode> { @@ -42,9 +41,8 @@ impl MediaElementAudioSourceNode { MediaElementSourceNodeMessage::GetAudioRenderer(sender), )); let audio_renderer = receiver.recv().unwrap(); - // XXX set audio renderer in player. - let media_element = &options.mediaElement; - let media_element = Dom::from_ref(&**media_element); + options.mediaElement.set_audio_renderer(audio_renderer); + let media_element = Dom::from_ref(&*options.mediaElement); Ok(MediaElementAudioSourceNode { node, media_element, @@ -57,7 +55,7 @@ impl MediaElementAudioSourceNode { context: &AudioContext, options: &MediaElementAudioSourceOptions, ) -> Fallible<DomRoot<MediaElementAudioSourceNode>> { - let node = MediaElementAudioSourceNode::new_inherited(window, context, options)?; + let node = MediaElementAudioSourceNode::new_inherited(context, options)?; Ok(reflect_dom_object( Box::new(node), window, |