diff options
author | Anthony Ramine <n.oxyde@gmail.com> | 2017-09-06 13:49:15 +0200 |
---|---|---|
committer | Anthony Ramine <n.oxyde@gmail.com> | 2017-09-06 13:50:56 +0200 |
commit | e169acd1d66c61746c0d6fa67d62b925e15940c5 (patch) | |
tree | 7bcef51f800635b1b11949630840ae4c4de6fa9a /components/script/dom/htmlmediaelement.rs | |
parent | f5e23a3a903a8142ff8993418142b0554f580c7d (diff) | |
download | servo-e169acd1d66c61746c0d6fa67d62b925e15940c5.tar.gz servo-e169acd1d66c61746c0d6fa67d62b925e15940c5.zip |
Put HTMLMediaElement first in its module
Diffstat (limited to 'components/script/dom/htmlmediaelement.rs')
-rw-r--r-- | components/script/dom/htmlmediaelement.rs | 348 |
1 files changed, 174 insertions, 174 deletions
diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index 965599e93c3..526672a5ad8 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -42,180 +42,6 @@ use std::sync::{Arc, Mutex}; use task_source::TaskSource; use time::{self, Timespec, Duration}; -struct HTMLMediaElementContext { - /// The element that initiated the request. - elem: Trusted<HTMLMediaElement>, - /// The response body received to date. - data: Vec<u8>, - /// The response metadata received to date. - metadata: Option<Metadata>, - /// The generation of the media element when this fetch started. - generation_id: u32, - /// Time of last progress notification. - next_progress_event: Timespec, - /// Url of resource requested. - url: ServoUrl, - /// Whether the media metadata has been completely received. - have_metadata: bool, - /// True if this response is invalid and should be ignored. - ignore_response: bool, -} - -impl FetchResponseListener for HTMLMediaElementContext { - fn process_request_body(&mut self) {} - - fn process_request_eof(&mut self) {} - - // https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list - fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>) { - self.metadata = metadata.ok().map(|m| { - match m { - FetchMetadata::Unfiltered(m) => m, - FetchMetadata::Filtered { unsafe_, .. } => unsafe_ - } - }); - - // => "If the media data cannot be fetched at all..." - let is_failure = self.metadata - .as_ref() - .and_then(|m| m.status - .as_ref() - .map(|&(s, _)| s < 200 || s >= 300)) - .unwrap_or(false); - if is_failure { - // Ensure that the element doesn't receive any further notifications - // of the aborted fetch. The dedicated failure steps will be executed - // when response_complete runs. - self.ignore_response = true; - } - } - - fn process_response_chunk(&mut self, mut payload: Vec<u8>) { - if self.ignore_response { - return; - } - - self.data.append(&mut payload); - - let elem = self.elem.root(); - - // https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list - // => "Once enough of the media data has been fetched to determine the duration..." - if !self.have_metadata { - self.check_metadata(&elem); - } else { - elem.change_ready_state(HAVE_CURRENT_DATA); - } - - // https://html.spec.whatwg.org/multipage/#concept-media-load-resource step 4, - // => "If mode is remote" step 2 - if time::get_time() > self.next_progress_event { - let window = window_from_node(&*elem); - window.dom_manipulation_task_source().queue_simple_event( - elem.upcast(), - atom!("progress"), - &window, - ); - self.next_progress_event = time::get_time() + Duration::milliseconds(350); - } - } - - // https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list - fn process_response_eof(&mut self, status: Result<(), NetworkError>) { - let elem = self.elem.root(); - - // => "If the media data can be fetched but is found by inspection to be in an unsupported - // format, or can otherwise not be rendered at all" - if !self.have_metadata { - elem.queue_dedicated_media_source_failure_steps(); - } - // => "Once the entire media resource has been fetched..." - else if status.is_ok() { - elem.change_ready_state(HAVE_ENOUGH_DATA); - - elem.upcast::<EventTarget>().fire_event(atom!("progress")); - - elem.network_state.set(NETWORK_IDLE); - - elem.upcast::<EventTarget>().fire_event(atom!("suspend")); - } - // => "If the connection is interrupted after some media data has been received..." - else if elem.ready_state.get() != HAVE_NOTHING { - // Step 2 - elem.error.set(Some(&*MediaError::new(&*window_from_node(&*elem), - MEDIA_ERR_NETWORK))); - - // Step 3 - elem.network_state.set(NETWORK_IDLE); - - // TODO: Step 4 - update delay load flag - - // Step 5 - elem.upcast::<EventTarget>().fire_event(atom!("error")); - } else { - // => "If the media data cannot be fetched at all..." - elem.queue_dedicated_media_source_failure_steps(); - } - - let document = document_from_node(&*elem); - document.finish_load(LoadType::Media(self.url.clone())); - } -} - -impl PreInvoke for HTMLMediaElementContext { - fn should_invoke(&self) -> bool { - //TODO: finish_load needs to run at some point if the generation changes. - self.elem.root().generation_id.get() == self.generation_id - } -} - -impl HTMLMediaElementContext { - fn new(elem: &HTMLMediaElement, url: ServoUrl) -> HTMLMediaElementContext { - HTMLMediaElementContext { - elem: Trusted::new(elem), - data: vec![], - metadata: None, - generation_id: elem.generation_id.get(), - next_progress_event: time::get_time() + Duration::milliseconds(350), - url: url, - have_metadata: false, - ignore_response: false, - } - } - - fn check_metadata(&mut self, elem: &HTMLMediaElement) { - match audio_video_metadata::get_format_from_slice(&self.data) { - Ok(audio_video_metadata::Metadata::Video(meta)) => { - let dur = meta.audio.duration.unwrap_or(::std::time::Duration::new(0, 0)); - *elem.video.borrow_mut() = Some(VideoMedia { - format: format!("{:?}", meta.format), - duration: Duration::seconds(dur.as_secs() as i64) + - Duration::nanoseconds(dur.subsec_nanos() as i64), - width: meta.dimensions.width, - height: meta.dimensions.height, - video: meta.video.unwrap_or("".to_owned()), - audio: meta.audio.audio, - }); - // Step 6 - elem.change_ready_state(HAVE_METADATA); - self.have_metadata = true; - } - _ => {} - } - } -} - -#[derive(HeapSizeOf, JSTraceable)] -pub struct VideoMedia { - format: String, - #[ignore_heap_size_of = "defined in time"] - duration: Duration, - width: u32, - height: u32, - video: String, - audio: Option<String>, -} - #[dom_struct] pub struct HTMLMediaElement { htmlelement: HTMLElement, @@ -230,6 +56,17 @@ pub struct HTMLMediaElement { video: DOMRefCell<Option<VideoMedia>>, } +#[derive(HeapSizeOf, JSTraceable)] +pub struct VideoMedia { + format: String, + #[ignore_heap_size_of = "defined in time"] + duration: Duration, + width: u32, + height: u32, + video: String, + audio: Option<String>, +} + impl HTMLMediaElement { pub fn new_inherited(tag_name: LocalName, prefix: Option<Prefix>, document: &Document) @@ -888,3 +725,166 @@ enum Resource { Object, Url(ServoUrl), } + +struct HTMLMediaElementContext { + /// The element that initiated the request. + elem: Trusted<HTMLMediaElement>, + /// The response body received to date. + data: Vec<u8>, + /// The response metadata received to date. + metadata: Option<Metadata>, + /// The generation of the media element when this fetch started. + generation_id: u32, + /// Time of last progress notification. + next_progress_event: Timespec, + /// Url of resource requested. + url: ServoUrl, + /// Whether the media metadata has been completely received. + have_metadata: bool, + /// True if this response is invalid and should be ignored. + ignore_response: bool, +} + +impl FetchResponseListener for HTMLMediaElementContext { + fn process_request_body(&mut self) {} + + fn process_request_eof(&mut self) {} + + // https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list + fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>) { + self.metadata = metadata.ok().map(|m| { + match m { + FetchMetadata::Unfiltered(m) => m, + FetchMetadata::Filtered { unsafe_, .. } => unsafe_ + } + }); + + // => "If the media data cannot be fetched at all..." + let is_failure = self.metadata + .as_ref() + .and_then(|m| m.status + .as_ref() + .map(|&(s, _)| s < 200 || s >= 300)) + .unwrap_or(false); + if is_failure { + // Ensure that the element doesn't receive any further notifications + // of the aborted fetch. The dedicated failure steps will be executed + // when response_complete runs. + self.ignore_response = true; + } + } + + fn process_response_chunk(&mut self, mut payload: Vec<u8>) { + if self.ignore_response { + return; + } + + self.data.append(&mut payload); + + let elem = self.elem.root(); + + // https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list + // => "Once enough of the media data has been fetched to determine the duration..." + if !self.have_metadata { + self.check_metadata(&elem); + } else { + elem.change_ready_state(HAVE_CURRENT_DATA); + } + + // https://html.spec.whatwg.org/multipage/#concept-media-load-resource step 4, + // => "If mode is remote" step 2 + if time::get_time() > self.next_progress_event { + let window = window_from_node(&*elem); + window.dom_manipulation_task_source().queue_simple_event( + elem.upcast(), + atom!("progress"), + &window, + ); + self.next_progress_event = time::get_time() + Duration::milliseconds(350); + } + } + + // https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list + fn process_response_eof(&mut self, status: Result<(), NetworkError>) { + let elem = self.elem.root(); + + // => "If the media data can be fetched but is found by inspection to be in an unsupported + // format, or can otherwise not be rendered at all" + if !self.have_metadata { + elem.queue_dedicated_media_source_failure_steps(); + } + // => "Once the entire media resource has been fetched..." + else if status.is_ok() { + elem.change_ready_state(HAVE_ENOUGH_DATA); + + elem.upcast::<EventTarget>().fire_event(atom!("progress")); + + elem.network_state.set(NETWORK_IDLE); + + elem.upcast::<EventTarget>().fire_event(atom!("suspend")); + } + // => "If the connection is interrupted after some media data has been received..." + else if elem.ready_state.get() != HAVE_NOTHING { + // Step 2 + elem.error.set(Some(&*MediaError::new(&*window_from_node(&*elem), + MEDIA_ERR_NETWORK))); + + // Step 3 + elem.network_state.set(NETWORK_IDLE); + + // TODO: Step 4 - update delay load flag + + // Step 5 + elem.upcast::<EventTarget>().fire_event(atom!("error")); + } else { + // => "If the media data cannot be fetched at all..." + elem.queue_dedicated_media_source_failure_steps(); + } + + let document = document_from_node(&*elem); + document.finish_load(LoadType::Media(self.url.clone())); + } +} + +impl PreInvoke for HTMLMediaElementContext { + fn should_invoke(&self) -> bool { + //TODO: finish_load needs to run at some point if the generation changes. + self.elem.root().generation_id.get() == self.generation_id + } +} + +impl HTMLMediaElementContext { + fn new(elem: &HTMLMediaElement, url: ServoUrl) -> HTMLMediaElementContext { + HTMLMediaElementContext { + elem: Trusted::new(elem), + data: vec![], + metadata: None, + generation_id: elem.generation_id.get(), + next_progress_event: time::get_time() + Duration::milliseconds(350), + url: url, + have_metadata: false, + ignore_response: false, + } + } + + fn check_metadata(&mut self, elem: &HTMLMediaElement) { + match audio_video_metadata::get_format_from_slice(&self.data) { + Ok(audio_video_metadata::Metadata::Video(meta)) => { + let dur = meta.audio.duration.unwrap_or(::std::time::Duration::new(0, 0)); + *elem.video.borrow_mut() = Some(VideoMedia { + format: format!("{:?}", meta.format), + duration: Duration::seconds(dur.as_secs() as i64) + + Duration::nanoseconds(dur.subsec_nanos() as i64), + width: meta.dimensions.width, + height: meta.dimensions.height, + video: meta.video.unwrap_or("".to_owned()), + audio: meta.audio.audio, + }); + // Step 6 + elem.change_ready_state(HAVE_METADATA); + self.have_metadata = true; + } + _ => {} + } + } +} |