diff options
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/bindings/trace.rs | 2 | ||||
-rw-r--r-- | components/script/dom/htmlmediaelement.rs | 31 | ||||
-rw-r--r-- | components/script/dom/htmlvideoelement.rs | 27 | ||||
-rw-r--r-- | components/script/dom/webglrenderingcontext.rs | 11 |
4 files changed, 60 insertions, 11 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 95bad8b4c4e..bf65eb1e87d 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -103,6 +103,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::frame::Frame; use servo_media::player::Player; use servo_media::streams::registry::MediaStreamId; use servo_media::streams::MediaStreamType; @@ -516,6 +517,7 @@ unsafe_no_jsmanaged_fields!(Point2D<f32>, Rect<Au>); unsafe_no_jsmanaged_fields!(Rect<f32>); unsafe_no_jsmanaged_fields!(CascadeData); unsafe_no_jsmanaged_fields!(WindowGLContext); +unsafe_no_jsmanaged_fields!(Frame); unsafe impl<'a> JSTraceable for &'a str { #[inline] diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index e3cb0dfb5b2..398a3ad40f1 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -136,6 +136,10 @@ impl FrameHolder { unreachable!(); } } + + fn get_frame(&self) -> Frame { + self.1.clone() + } } pub struct MediaFrameRenderer { @@ -193,12 +197,12 @@ impl FrameRenderer for MediaFrameRenderer { ImageData::Raw(frame.get_data()), &webrender_api::DirtyRect::All, ); - } else if self.player_id.is_some() { - self.current_frame_holder - .get_or_insert_with(|| FrameHolder::new(frame.clone())) - .set(frame); } + self.current_frame_holder + .get_or_insert_with(|| FrameHolder::new(frame.clone())) + .set(frame); + if let Some(old_image_key) = self.old_frame.take() { txn.delete_image(old_image_key); } @@ -220,9 +224,6 @@ impl FrameRenderer for MediaFrameRenderer { TextureTarget::Default }; - self.current_frame_holder - .get_or_insert_with(|| FrameHolder::new(frame.clone())) - .set(frame); ImageData::External(ExternalImageData { id: ExternalImageId(self.player_id.unwrap()), channel_index: 0, @@ -231,6 +232,11 @@ impl FrameRenderer for MediaFrameRenderer { } else { ImageData::Raw(frame.get_data()) }; + + self.current_frame_holder + .get_or_insert_with(|| FrameHolder::new(frame.clone())) + .set(frame); + txn.add_image(new_image_key, descriptor, image_data, None); }, None => { @@ -244,7 +250,6 @@ impl FrameRenderer for MediaFrameRenderer { TextureTarget::Default }; - self.current_frame_holder = Some(FrameHolder::new(frame)); ImageData::External(ExternalImageData { id: ExternalImageId(self.player_id.unwrap()), channel_index: 0, @@ -253,6 +258,9 @@ impl FrameRenderer for MediaFrameRenderer { } else { ImageData::Raw(frame.get_data()) }; + + self.current_frame_holder = Some(FrameHolder::new(frame)); + txn.add_image(image_key, descriptor, image_data, None); }, } @@ -1853,6 +1861,13 @@ impl HTMLMediaElement { document_from_node(self).unregister_media_controls(&id); } } + + pub fn get_current_frame(&self) -> Option<Frame> { + match self.frame_renderer.lock().unwrap().current_frame_holder { + Some(ref holder) => Some(holder.get_frame()), + None => return None, + } + } } // XXX Placeholder for [https://github.com/servo/servo/issues/22293] diff --git a/components/script/dom/htmlvideoelement.rs b/components/script/dom/htmlvideoelement.rs index e95a2ca8ccd..bca18c35a2b 100644 --- a/components/script/dom/htmlvideoelement.rs +++ b/components/script/dom/htmlvideoelement.rs @@ -23,6 +23,7 @@ use crate::fetch::FetchCanceller; use crate::image_listener::{add_cache_listener_for_element, ImageCacheListener}; use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener}; use dom_struct::dom_struct; +use euclid::default::Size2D; use html5ever::{LocalName, Prefix}; use ipc_channel::ipc; use ipc_channel::router::ROUTER; @@ -34,6 +35,7 @@ use net_traits::{ CoreResourceMsg, FetchChannels, FetchMetadata, FetchResponseListener, FetchResponseMsg, }; use net_traits::{NetworkError, ResourceFetchTiming, ResourceTimingType}; +use servo_media::player::frame::Frame; use servo_url::ServoUrl; use std::cell::Cell; use std::sync::{Arc, Mutex}; @@ -55,6 +57,9 @@ pub struct HTMLVideoElement { /// Load event blocker. Will block the load event while the poster frame /// is being fetched. load_blocker: DomRefCell<Option<LoadBlocker>>, + /// A copy of the last frame + #[ignore_malloc_size_of = "Frame"] + last_frame: DomRefCell<Option<Frame>>, } impl HTMLVideoElement { @@ -70,6 +75,7 @@ impl HTMLVideoElement { generation_id: Cell::new(0), poster_frame_canceller: DomRefCell::new(Default::default()), load_blocker: Default::default(), + last_frame: Default::default(), } } @@ -108,6 +114,27 @@ impl HTMLVideoElement { LoadBlocker::terminate(&mut *self.load_blocker.borrow_mut()); } + pub fn get_current_frame_data(&self) -> Option<(Option<ipc::IpcSharedMemory>, Size2D<u32>)> { + let frame = self.htmlmediaelement.get_current_frame(); + if frame.is_some() { + *self.last_frame.borrow_mut() = frame; + } + + match self.last_frame.borrow().as_ref() { + Some(frame) => { + let size = Size2D::new(frame.get_width() as u32, frame.get_height() as u32); + if !frame.is_gl_texture() { + let data = Some(ipc::IpcSharedMemory::from_bytes(&frame.get_data())); + Some((data, size)) + } else { + // XXX(victor): here we only have the GL texture ID. + Some((None, size)) + } + }, + None => None, + } + } + /// https://html.spec.whatwg.org/multipage/#poster-frame fn fetch_poster_frame(&self, poster_url: &str) { // Step 1. diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 46b9c72c6ca..f8350759dd8 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -604,9 +604,14 @@ impl WebGLRenderingContext { return Ok(None); } }, - TexImageSource::HTMLVideoElement(_) => { - // TODO: https://github.com/servo/servo/issues/6711 - return Ok(None); + TexImageSource::HTMLVideoElement(video) => match video.get_current_frame_data() { + Some((data, size)) => { + let data = data.unwrap_or_else(|| { + IpcSharedMemory::from_bytes(&vec![0; size.area() as usize * 4]) + }); + TexPixels::new(data, size, PixelFormat::BGRA8, false) + }, + None => return Ok(None), }, })) } |