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;