MediaElementAudioSourceNode: set audio renderer

This commit is contained in:
Fernando Jiménez Moreno 2019-11-07 17:35:10 +01:00
parent 03485d730f
commit a72e46f9c8
3 changed files with 29 additions and 8 deletions

View file

@ -107,6 +107,7 @@ use servo_media::audio::context::AudioContext;
use servo_media::audio::graph::NodeId; use servo_media::audio::graph::NodeId;
use servo_media::audio::panner_node::{DistanceModel, PanningModel}; use servo_media::audio::panner_node::{DistanceModel, PanningModel};
use servo_media::audio::param::ParamType; use servo_media::audio::param::ParamType;
use servo_media::player::audio::AudioRenderer;
use servo_media::player::video::VideoFrame; use servo_media::player::video::VideoFrame;
use servo_media::player::Player; use servo_media::player::Player;
use servo_media::streams::registry::MediaStreamId; use servo_media::streams::registry::MediaStreamId;
@ -534,6 +535,7 @@ unsafe_no_jsmanaged_fields!(CascadeData);
unsafe_no_jsmanaged_fields!(WindowGLContext); unsafe_no_jsmanaged_fields!(WindowGLContext);
unsafe_no_jsmanaged_fields!(VideoFrame); unsafe_no_jsmanaged_fields!(VideoFrame);
unsafe_no_jsmanaged_fields!(WebGLContextId); unsafe_no_jsmanaged_fields!(WebGLContextId);
unsafe_no_jsmanaged_fields!(Arc<Mutex<dyn AudioRenderer>>);
unsafe impl<'a> JSTraceable for &'a str { unsafe impl<'a> JSTraceable for &'a str {
#[inline] #[inline]

View file

@ -79,6 +79,7 @@ use net_traits::{CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseLis
use net_traits::{NetworkError, ResourceFetchTiming, ResourceTimingType}; use net_traits::{NetworkError, ResourceFetchTiming, ResourceTimingType};
use script_layout_interface::HTMLMediaData; use script_layout_interface::HTMLMediaData;
use servo_config::pref; use servo_config::pref;
use servo_media::player::audio::AudioRenderer;
use servo_media::player::video::{VideoFrame, VideoFrameRenderer}; use servo_media::player::video::{VideoFrame, VideoFrameRenderer};
use servo_media::player::{PlaybackState, Player, PlayerError, PlayerEvent, SeekLock, StreamType}; use servo_media::player::{PlaybackState, Player, PlayerError, PlayerEvent, SeekLock, StreamType};
use servo_media::{ClientContextId, ServoMedia, SupportsMediaType}; use servo_media::{ClientContextId, ServoMedia, SupportsMediaType};
@ -326,6 +327,8 @@ pub struct HTMLMediaElement {
player: DomRefCell<Option<Arc<Mutex<dyn Player>>>>, player: DomRefCell<Option<Arc<Mutex<dyn Player>>>>,
#[ignore_malloc_size_of = "Arc"] #[ignore_malloc_size_of = "Arc"]
video_renderer: Arc<Mutex<MediaFrameRenderer>>, 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 /// https://html.spec.whatwg.org/multipage/#show-poster-flag
show_poster: Cell<bool>, show_poster: Cell<bool>,
/// https://html.spec.whatwg.org/multipage/#dom-media-duration /// https://html.spec.whatwg.org/multipage/#dom-media-duration
@ -413,6 +416,7 @@ impl HTMLMediaElement {
video_renderer: Arc::new(Mutex::new(MediaFrameRenderer::new( video_renderer: Arc::new(Mutex::new(MediaFrameRenderer::new(
document.window().get_webrender_api_sender(), document.window().get_webrender_api_sender(),
))), ))),
audio_renderer: Default::default(),
show_poster: Cell::new(true), show_poster: Cell::new(true),
duration: Cell::new(f64::NAN), duration: Cell::new(f64::NAN),
playback_position: Cell::new(0.), playback_position: Cell::new(0.),
@ -1325,11 +1329,14 @@ impl HTMLMediaElement {
let window = window_from_node(self); let window = window_from_node(self);
let (action_sender, action_receiver) = ipc::channel::<PlayerEvent>().unwrap(); 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::HTMLAudioElement => None,
HTMLMediaElementTypeId::HTMLVideoElement => Some(self.video_renderer.clone()), HTMLMediaElementTypeId::HTMLVideoElement => Some(self.video_renderer.clone()),
}; };
let audio_renderer = self.audio_renderer.borrow().as_ref().map(|r| r.clone());
let pipeline_id = window let pipeline_id = window
.pipeline_id() .pipeline_id()
.expect("Cannot create player outside of a pipeline"); .expect("Cannot create player outside of a pipeline");
@ -1339,8 +1346,8 @@ impl HTMLMediaElement {
&client_context_id, &client_context_id,
stream_type, stream_type,
action_sender, action_sender,
renderer, video_renderer,
None, audio_renderer,
Box::new(window.get_player_context()), Box::new(window.get_player_context()),
); );
@ -1862,6 +1869,20 @@ impl HTMLMediaElement {
None => return None, 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] // XXX Placeholder for [https://github.com/servo/servo/issues/22293]

View file

@ -26,7 +26,6 @@ pub struct MediaElementAudioSourceNode {
impl MediaElementAudioSourceNode { impl MediaElementAudioSourceNode {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
fn new_inherited( fn new_inherited(
window: &Window,
context: &AudioContext, context: &AudioContext,
options: &MediaElementAudioSourceOptions, options: &MediaElementAudioSourceOptions,
) -> Fallible<MediaElementAudioSourceNode> { ) -> Fallible<MediaElementAudioSourceNode> {
@ -42,9 +41,8 @@ impl MediaElementAudioSourceNode {
MediaElementSourceNodeMessage::GetAudioRenderer(sender), MediaElementSourceNodeMessage::GetAudioRenderer(sender),
)); ));
let audio_renderer = receiver.recv().unwrap(); let audio_renderer = receiver.recv().unwrap();
// XXX set audio renderer in player. options.mediaElement.set_audio_renderer(audio_renderer);
let media_element = &options.mediaElement; let media_element = Dom::from_ref(&*options.mediaElement);
let media_element = Dom::from_ref(&**media_element);
Ok(MediaElementAudioSourceNode { Ok(MediaElementAudioSourceNode {
node, node,
media_element, media_element,
@ -57,7 +55,7 @@ impl MediaElementAudioSourceNode {
context: &AudioContext, context: &AudioContext,
options: &MediaElementAudioSourceOptions, options: &MediaElementAudioSourceOptions,
) -> Fallible<DomRoot<MediaElementAudioSourceNode>> { ) -> Fallible<DomRoot<MediaElementAudioSourceNode>> {
let node = MediaElementAudioSourceNode::new_inherited(window, context, options)?; let node = MediaElementAudioSourceNode::new_inherited(context, options)?;
Ok(reflect_dom_object( Ok(reflect_dom_object(
Box::new(node), Box::new(node),
window, window,