From 243b4e1a39c7f7feca71eb9fe8bd094059a2bdd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jim=C3=A9nez=20Moreno?= Date: Wed, 12 Dec 2018 13:06:52 +0100 Subject: [PATCH 1/3] Do not set player EOS. Set input size only if it changes --- components/script/dom/htmlmediaelement.rs | 39 ++++++++++++++++------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index bbdea90dee9..141ad5c86be 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -45,7 +45,7 @@ use crate::script_thread::ScriptThread; use crate::task_source::TaskSource; use dom_struct::dom_struct; use headers_core::HeaderMapExt; -use headers_ext::ContentLength; +use headers_ext::{ContentLength, ContentRange}; use html5ever::{LocalName, Prefix}; use http::header::{self, HeaderMap, HeaderValue}; use ipc_channel::ipc; @@ -196,6 +196,8 @@ pub struct HTMLMediaElement { played: Rc>, /// https://html.spec.whatwg.org/multipage/#dom-media-texttracks text_tracks_list: MutNullableDom, + /// Expected content length of the media asset being fetched or played. + content_length: Cell>, } /// @@ -249,6 +251,7 @@ impl HTMLMediaElement { resource_url: DomRefCell::new(None), played: Rc::new(DomRefCell::new(TimeRangesContainer::new())), text_tracks_list: Default::default(), + content_length: Cell::new(None), } } @@ -1375,7 +1378,7 @@ impl HTMLMediaElementMethods for HTMLMediaElement { // https://html.spec.whatwg.org/multipage/#dom-media-fastseek fn FastSeek(&self, time: Finite) { - self.seek(*time, /* approximat_for_speed */ true); + self.seek(*time, /* approximate_for_speed */ true); } // https://html.spec.whatwg.org/multipage/#dom-media-played @@ -1534,6 +1537,8 @@ impl FetchResponseListener for HTMLMediaElementContext { fn process_request_eof(&mut self) {} fn process_response(&mut self, metadata: Result) { + let elem = self.elem.root(); + self.metadata = metadata.ok().map(|m| match m { FetchMetadata::Unfiltered(m) => m, FetchMetadata::Filtered { unsafe_, .. } => unsafe_, @@ -1541,9 +1546,25 @@ impl FetchResponseListener for HTMLMediaElementContext { if let Some(metadata) = self.metadata.as_ref() { if let Some(headers) = metadata.headers.as_ref() { - if let Some(content_length) = headers.typed_get::() { - if let Err(e) = self.elem.root().player.set_input_size(content_length.0) { - eprintln!("Could not set player input size {:?}", e); + // For range requests we get the size of the media asset from the Content-Range + // header. Otherwise, we get it from the Content-Length header. + let content_length = + if let Some(content_range) = headers.typed_get::() { + content_range.bytes_len() + } else if let Some(content_length) = headers.typed_get::() { + Some(content_length.0) + } else { + None + }; + + // We only set the expected input size if it changes. + if content_length != elem.content_length.get() { + if let Some(content_length) = content_length { + if let Err(e) = self.elem.root().player.set_input_size(content_length) { + warn!("Could not set player input size {:?}", e); + } else { + elem.content_length.set(Some(content_length)); + } } } } @@ -1560,7 +1581,6 @@ impl FetchResponseListener for HTMLMediaElementContext { // Ensure that the element doesn't receive any further notifications // of the aborted fetch. self.ignore_response = true; - let elem = self.elem.root(); elem.fetch_canceller.borrow_mut().cancel(); elem.queue_dedicated_media_source_failure_steps(); } @@ -1598,13 +1618,8 @@ impl FetchResponseListener for HTMLMediaElementContext { // An error was received previously, skip processing the payload. return; } + let elem = self.elem.root(); - - // Signal the eos to player. - if let Err(e) = elem.player.end_of_stream() { - eprintln!("Could not signal EOS to player {:?}", e); - } - if status.is_ok() { if elem.ready_state.get() == ReadyState::HaveNothing { // Make sure that we don't skip the HaveMetadata and HaveCurrentData From 707b490c0f1d5f09ac481ae903e349dd2ddd97c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jim=C3=A9nez=20Moreno?= Date: Wed, 12 Dec 2018 16:52:37 +0100 Subject: [PATCH 2/3] Signal EOS if media request fails --- components/script/dom/htmlmediaelement.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index 141ad5c86be..15d0090cba7 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -1614,12 +1614,16 @@ impl FetchResponseListener for HTMLMediaElementContext { // https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list fn process_response_eof(&mut self, status: Result) { + let elem = self.elem.root(); if self.ignore_response { - // An error was received previously, skip processing the payload. + // An error was received previously, skip processing the payload + // and notify the media backend that we are done pushing data. + if let Err(e) = elem.player.end_of_stream() { + warn!("Could not signal EOS to player {:?}", e); + } return; } - let elem = self.elem.root(); if status.is_ok() { if elem.ready_state.get() == ReadyState::HaveNothing { // Make sure that we don't skip the HaveMetadata and HaveCurrentData From 881889824053cf3892c30e6b66a29a1720781dae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jim=C3=A9nez=20Moreno?= Date: Wed, 12 Dec 2018 17:08:36 +0100 Subject: [PATCH 3/3] Do not move to HaveEnoughData state if no media data is fetched from the network --- components/script/dom/htmlmediaelement.rs | 12 ++++++++---- .../load-events-networkState.html.ini | 4 ---- ...urce-selection-invoke-insert-into-iframe.html.ini | 4 ---- ...urce-selection-invoke-pause-networkState.html.ini | 4 ---- ...invoke-remove-from-document-networkState.html.ini | 4 ---- 5 files changed, 8 insertions(+), 20 deletions(-) delete mode 100644 tests/wpt/metadata/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-events-networkState.html.ini delete mode 100644 tests/wpt/metadata/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-iframe.html.ini delete mode 100644 tests/wpt/metadata/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause-networkState.html.ini delete mode 100644 tests/wpt/metadata/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document-networkState.html.ini diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index 15d0090cba7..f843554190a 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -1528,6 +1528,8 @@ struct HTMLMediaElementContext { resource_timing: ResourceFetchTiming, /// url for the resource url: ServoUrl, + /// Amount of data fetched. + bytes_fetched: usize, } // https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list @@ -1592,8 +1594,9 @@ impl FetchResponseListener for HTMLMediaElementContext { return; } - let elem = self.elem.root(); + self.bytes_fetched += payload.len(); + let elem = self.elem.root(); // Push input data into the player. if let Err(e) = elem.player.push_data(payload) { eprintln!("Could not push input data to player {:?}", e); @@ -1617,14 +1620,14 @@ impl FetchResponseListener for HTMLMediaElementContext { let elem = self.elem.root(); if self.ignore_response { // An error was received previously, skip processing the payload - // and notify the media backend that we are done pushing data. + // and notify the media backend that we are done pushing data. if let Err(e) = elem.player.end_of_stream() { warn!("Could not signal EOS to player {:?}", e); } return; } - if status.is_ok() { + if status.is_ok() && self.bytes_fetched != 0 { if elem.ready_state.get() == ReadyState::HaveNothing { // Make sure that we don't skip the HaveMetadata and HaveCurrentData // states for short streams. @@ -1711,7 +1714,8 @@ impl HTMLMediaElementContext { next_progress_event: time::get_time() + Duration::milliseconds(350), ignore_response: false, resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource), - url: url, + url, + bytes_fetched: 0, } } } diff --git a/tests/wpt/metadata/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-events-networkState.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-events-networkState.html.ini deleted file mode 100644 index 95be7126728..00000000000 --- a/tests/wpt/metadata/html/semantics/embedded-content/media-elements/loading-the-media-resource/load-events-networkState.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[load-events-networkState.html] - [NETWORK_NO_SOURCE] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-iframe.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-iframe.html.ini deleted file mode 100644 index dd5f01686e9..00000000000 --- a/tests/wpt/metadata/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-insert-into-iframe.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[resource-selection-invoke-insert-into-iframe.html] - [NOT invoking resource selection by inserting into other document with src set] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause-networkState.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause-networkState.html.ini deleted file mode 100644 index 80becaced04..00000000000 --- a/tests/wpt/metadata/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-pause-networkState.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[resource-selection-invoke-pause-networkState.html] - [NOT invoking resource selection with pause() when networkState is not NETWORK_EMPTY] - expected: FAIL - diff --git a/tests/wpt/metadata/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document-networkState.html.ini b/tests/wpt/metadata/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document-networkState.html.ini deleted file mode 100644 index cbd728cd5fd..00000000000 --- a/tests/wpt/metadata/html/semantics/embedded-content/media-elements/loading-the-media-resource/resource-selection-invoke-remove-from-document-networkState.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[resource-selection-invoke-remove-from-document-networkState.html] - [NOT invoking resource selection with implicit pause() when networkState is not NETWORK_EMPTY] - expected: FAIL -