diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index 292d1b8a6a5..f40eb2861b8 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -26,7 +26,8 @@ use dom::eventtarget::EventTarget; use dom::htmlelement::HTMLElement; use dom::htmlsourceelement::HTMLSourceElement; use dom::mediaerror::MediaError; -use dom::node::{window_from_node, document_from_node, Node, UnbindContext}; +use dom::mediaframerenderer::MediaFrameRenderer; +use dom::node::{document_from_node, window_from_node, Node, NodeDamage, UnbindContext}; use dom::promise::Promise; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; @@ -51,6 +52,7 @@ use task_source::{TaskSource, TaskSourceName}; use time::{self, Timespec, Duration}; unsafe_no_jsmanaged_fields!(Arc>>); +unsafe_no_jsmanaged_fields!(MediaFrameRenderer); #[dom_struct] // FIXME(nox): A lot of tasks queued for this element should probably be in the @@ -89,6 +91,8 @@ pub struct HTMLMediaElement { have_metadata: Cell, #[ignore_malloc_size_of = "servo_media"] player: Arc>>, + #[ignore_malloc_size_of = "oops"] + frame_renderer: MediaFrameRenderer, } /// @@ -133,6 +137,7 @@ impl HTMLMediaElement { player: Arc::new(Mutex::new( ServoMedia::get().unwrap().create_player().unwrap(), )), + frame_renderer: MediaFrameRenderer::new(document.window().get_webrender_api_sender()), } } @@ -835,6 +840,10 @@ impl HTMLMediaElement { .lock() .unwrap() .register_event_handler(action_sender); + self.player + .lock() + .unwrap() + .register_frame_renderer(Arc::new(self.frame_renderer.clone())); self.player.lock().unwrap().setup().unwrap(); let trusted_node = Trusted::new(self); @@ -882,7 +891,9 @@ impl HTMLMediaElement { _ => {} }, PlayerEvent::EndOfStream => {} - PlayerEvent::FrameUpdated => {} + PlayerEvent::FrameUpdated => { + self.upcast::().dirty(NodeDamage::OtherNodeDamage); + } PlayerEvent::Error => { self.error.set(Some(&*MediaError::new( &*window_from_node(self), diff --git a/components/script/dom/mediaframerenderer.rs b/components/script/dom/mediaframerenderer.rs new file mode 100644 index 00000000000..698051885a7 --- /dev/null +++ b/components/script/dom/mediaframerenderer.rs @@ -0,0 +1,86 @@ +use servo_media::player::frame::{Frame, FrameRenderer}; +use std::mem; +use std::sync::{Arc, Mutex}; +use webrender_api::{ + ImageData, ImageDescriptor, ImageFormat, ImageKey, RenderApi, RenderApiSender, Transaction, +}; + +#[derive(Clone)] +pub struct MediaFrameRenderer { + inner: Arc>, +} + +impl MediaFrameRenderer { + pub fn new(render_api_sender: RenderApiSender) -> MediaFrameRenderer { + MediaFrameRenderer { + inner: Arc::new(Mutex::new(MediaFrameRendererInner { + api: render_api_sender.create_api(), + current_frame: None, + old_frame: None, + very_old_frame: None, + })), + } + } +} + +impl FrameRenderer for MediaFrameRenderer { + fn render(&self, frame: Frame) { + self.inner.lock().unwrap().render(frame); + } +} + +struct MediaFrameRendererInner { + api: RenderApi, + current_frame: Option<(ImageKey, i32, i32)>, + old_frame: Option, + very_old_frame: Option, +} + +impl MediaFrameRendererInner { + fn render(&mut self, frame: Frame) { + let descriptor = ImageDescriptor::new( + frame.get_width() as u32, + frame.get_height() as u32, + ImageFormat::BGRA8, + false, + false, + ); + + let mut txn = Transaction::new(); + + //let image_data = ImageData::new_shared(frame.get_data().clone()); + let image_data = ImageData::Raw(frame.get_data().clone()); + + if let Some(old_image_key) = mem::replace(&mut self.very_old_frame, self.old_frame.take()) { + txn.delete_image(old_image_key); + } + + match self.current_frame { + Some((ref image_key, ref mut width, ref mut height)) + if *width == frame.get_width() && *height == frame.get_height() => + { + txn.update_image(*image_key, descriptor, image_data, None); + + if let Some(old_image_key) = self.old_frame.take() { + txn.delete_image(old_image_key); + } + } + Some((ref mut image_key, ref mut width, ref mut height)) => { + self.old_frame = Some(*image_key); + + let new_image_key = self.api.generate_image_key(); + txn.add_image(new_image_key, descriptor, image_data, None); + *image_key = new_image_key; + *width = frame.get_width(); + *height = frame.get_height(); + } + None => { + let image_key = self.api.generate_image_key(); + txn.add_image(image_key, descriptor, image_data, None); + self.current_frame = Some((image_key, frame.get_width(), frame.get_height())); + } + } + + self.api.update_resources(txn.resource_updates); + } +} diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 07425cccae1..10ed49f99a2 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -390,6 +390,7 @@ pub mod inputevent; pub mod keyboardevent; pub mod location; pub mod mediaerror; +pub mod mediaframerenderer; pub mod medialist; pub mod mediaquerylist; pub mod mediaquerylistevent;