mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
htmlmediaelement: Support seek requests for non seekable fetch context
According to specification the data:// URL protocol doesn't support range request so be able make any seek request to required content position let's allow for non seekable fetch context discard fetched content bytes until seek offset. https://fetch.spec.whatwg.org/#scheme-fetch Some scheme URLs (like data:// URL) doesn't expose "Content-Length" header in response so the total expected size of the stream is unknown and it causes some additional seek request (SeekData) from the media player. Try to post configure stream size after we reached fetch EOS response. Related source code which breaks WPT tests: tests/wpt/tests/html/canvas/element/manual/imagebitmap/common.sub.js#L56-L78 Testing: Improvements in the following tests: - html/canvas/element/manual/imagebitmap/createImageBitmap* - mixed-content/gen/top.***/opt-in/video-tag.https.html - webgl/tests/conformance/textures/misc/texture-srgb-upload.html Fixes: servo#32645 Fixes: servo#32745 Fixes: servo#34119 Fixes: servo#34120 Fixes: servo#34151 Signed-off-by: Andrei Volykhin <andrei.volykhin@gmail.com>
This commit is contained in:
parent
d246e80844
commit
0706594469
10 changed files with 52 additions and 42 deletions
|
@ -2892,12 +2892,12 @@ struct HTMLMediaElementFetchListener {
|
|||
url: ServoUrl,
|
||||
/// Expected content length of the media asset being fetched or played.
|
||||
expected_content_length: Option<u64>,
|
||||
/// Number of the last byte fetched from the network for the ongoing
|
||||
/// request. It is only reset to 0 if we reach EOS. Seek requests
|
||||
/// set it to the requested position. Requests triggered after an
|
||||
/// EnoughData event uses this value to restart the download from
|
||||
/// the last fetched position.
|
||||
latest_fetched_content: u64,
|
||||
/// Actual content length of the media asset was fetched.
|
||||
fetched_content_length: u64,
|
||||
/// Discarded content length from the network for the ongoing
|
||||
/// request if range requests are not supported. Seek requests set it
|
||||
/// to the required position (in bytes).
|
||||
content_length_to_discard: u64,
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list
|
||||
|
@ -2986,10 +2986,10 @@ impl FetchResponseListener for HTMLMediaElementFetchListener {
|
|||
}
|
||||
}
|
||||
|
||||
fn process_response_chunk(&mut self, _: RequestId, payload: Vec<u8>) {
|
||||
fn process_response_chunk(&mut self, _: RequestId, chunk: Vec<u8>) {
|
||||
let elem = self.elem.root();
|
||||
|
||||
let payload_len = payload.len() as u64;
|
||||
self.fetched_content_length += chunk.len() as u64;
|
||||
|
||||
// If an error was received previously, we skip processing the payload.
|
||||
if let Some(ref mut current_fetch_context) = *elem.current_fetch_context.borrow_mut() {
|
||||
|
@ -2997,6 +2997,24 @@ impl FetchResponseListener for HTMLMediaElementFetchListener {
|
|||
return;
|
||||
}
|
||||
|
||||
// Discard chunk of the response body if fetch context doesn't
|
||||
// support range requests.
|
||||
let payload = if !current_fetch_context.is_seekable() &&
|
||||
self.content_length_to_discard != 0
|
||||
{
|
||||
if chunk.len() as u64 > self.content_length_to_discard {
|
||||
let shrink_chunk = chunk[self.content_length_to_discard as usize..].to_vec();
|
||||
self.content_length_to_discard = 0;
|
||||
shrink_chunk
|
||||
} else {
|
||||
// Completely discard this response chunk.
|
||||
self.content_length_to_discard -= chunk.len() as u64;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
chunk
|
||||
};
|
||||
|
||||
if let Err(e) = {
|
||||
let mut data_source = current_fetch_context.data_source().borrow_mut();
|
||||
data_source.add_buffer_to_queue(DataBuffer::Payload(payload));
|
||||
|
@ -3013,8 +3031,6 @@ impl FetchResponseListener for HTMLMediaElementFetchListener {
|
|||
}
|
||||
}
|
||||
|
||||
self.latest_fetched_content += payload_len;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#concept-media-load-resource step 4,
|
||||
// => "If mode is remote" step 2
|
||||
if Instant::now() > self.next_progress_event {
|
||||
|
@ -3039,6 +3055,26 @@ impl FetchResponseListener for HTMLMediaElementFetchListener {
|
|||
// There are no more chunks of the response body forthcoming, so we can
|
||||
// go ahead and notify the media backend not to expect any further data.
|
||||
if let Some(ref mut current_fetch_context) = *elem.current_fetch_context.borrow_mut() {
|
||||
// On initial state change READY -> PAUSED the media player perform
|
||||
// seek to initial position by event with seek segment (TIME format)
|
||||
// while media stack operates in BYTES format and configuring segment
|
||||
// start and stop positions without the total size of the stream is not
|
||||
// possible. As fallback the media player perform seek with BYTES format
|
||||
// and initiate seek request via "seek-data" callback with required offset.
|
||||
if self.expected_content_length.is_none() && self.fetched_content_length != 0 {
|
||||
if let Err(e) = elem
|
||||
.player
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_input_size(self.fetched_content_length)
|
||||
{
|
||||
warn!("Could not set player input size {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
let mut data_source = current_fetch_context.data_source().borrow_mut();
|
||||
|
||||
data_source.add_buffer_to_queue(DataBuffer::EndOfStream);
|
||||
|
@ -3051,7 +3087,7 @@ impl FetchResponseListener for HTMLMediaElementFetchListener {
|
|||
}
|
||||
}
|
||||
|
||||
if status.is_ok() && self.latest_fetched_content != 0 {
|
||||
if status.is_ok() && self.fetched_content_length != 0 {
|
||||
elem.upcast::<EventTarget>()
|
||||
.fire_event(atom!("progress"), CanGc::note());
|
||||
|
||||
|
@ -3157,7 +3193,8 @@ impl HTMLMediaElementFetchListener {
|
|||
resource_timing: ResourceFetchTiming::new(ResourceTimingType::Resource),
|
||||
url,
|
||||
expected_content_length: None,
|
||||
latest_fetched_content: offset,
|
||||
fetched_content_length: 0,
|
||||
content_length_to_discard: offset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[createImageBitmap-colorSpaceConversion.html]
|
||||
expected: ERROR
|
||||
[createImageBitmap from a bitmap HTMLImageElement, and drawImage on the created ImageBitmap with colorSpaceConversion: none]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[createImageBitmap-drawImage.html]
|
||||
expected: ERROR
|
||||
[createImageBitmap from an OffscreenCanvas resized, and drawImage on the created ImageBitmap]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[createImageBitmap-flipY.html]
|
||||
expected: ERROR
|
||||
[createImageBitmap from a vector SVGImageElement imageOrientation: "none", and drawImage on the created ImageBitmap]
|
||||
expected: NOTRUN
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[createImageBitmap-invalid-args.html]
|
||||
expected: ERROR
|
||||
[createImageBitmap with a vector HTMLImageElement source and sw set to 0]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -138,18 +137,12 @@
|
|||
[createImageBitmap with a vector SVGImageElement source and a value between 0 and 1 in resizeHeight]
|
||||
expected: FAIL
|
||||
|
||||
[createImageBitmap with an HTMLVideoElement from a data URL source and a value between 0 and 1 in resizeWidth]
|
||||
expected: FAIL
|
||||
|
||||
[createImageBitmap with a vector SVGImageElement source and a value of 0 in resizeHeight]
|
||||
expected: FAIL
|
||||
|
||||
[createImageBitmap with a bitmap SVGImageElement source and a value between 0 and 1 in resizeHeight]
|
||||
expected: FAIL
|
||||
|
||||
[createImageBitmap with an HTMLVideoElement from a data URL source and a value of 0 in resizeHeight]
|
||||
expected: FAIL
|
||||
|
||||
[createImageBitmap with an ImageBitmap source and a value of 0 in resizeHeight]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -162,11 +155,5 @@
|
|||
[createImageBitmap with a bitmap SVGImageElement source and a value of 0 int resizeWidth]
|
||||
expected: FAIL
|
||||
|
||||
[createImageBitmap with an HTMLVideoElement from a data URL source and a value of 0 int resizeWidth]
|
||||
expected: FAIL
|
||||
|
||||
[createImageBitmap with an HTMLVideoElement from a data URL source and a value between 0 and 1 in resizeHeight]
|
||||
expected: FAIL
|
||||
|
||||
[createImageBitmap with a vector SVGImageElement source and a value between 0 and 1 in resizeWidth]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[createImageBitmap-premultiplyAlpha.html]
|
||||
expected: ERROR
|
||||
[createImageBitmap: from ImageData, unpremultiplied, drawn to canvas]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[createImageBitmap-transfer.html]
|
||||
expected: ERROR
|
||||
[Transfer ImageBitmap created from a vector HTMLImageElement]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
[video-tag.https.html]
|
||||
expected: TIMEOUT
|
||||
[Mixed-Content: Expects allowed for video-tag to same-https origin and keep-scheme redirection from https context.]
|
||||
expected: TIMEOUT
|
||||
|
||||
[Mixed-Content: Expects allowed for video-tag to same-https origin and no-redirect redirection from https context.]
|
||||
expected: NOTRUN
|
||||
|
||||
[Mixed-Content: Expects blocked for video-tag to cross-http origin and keep-scheme redirection from https context.]
|
||||
expected: NOTRUN
|
||||
expected: TIMEOUT
|
||||
|
||||
[Mixed-Content: Expects blocked for video-tag to cross-http origin and no-redirect redirection from https context.]
|
||||
expected: NOTRUN
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
[video-tag.https.html]
|
||||
expected: TIMEOUT
|
||||
[Mixed-Content: Expects allowed for video-tag to same-https origin and no-redirect redirection from https context.]
|
||||
expected: TIMEOUT
|
||||
|
||||
[Mixed-Content: Expects blocked for video-tag to cross-http origin and no-redirect redirection from https context.]
|
||||
expected: NOTRUN
|
||||
expected: TIMEOUT
|
||||
|
||||
[Mixed-Content: Expects blocked for video-tag to same-http origin and no-redirect redirection from https context.]
|
||||
expected: NOTRUN
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[texture-srgb-upload.html]
|
||||
expected: TIMEOUT
|
||||
expected: ERROR
|
||||
[Overall test]
|
||||
expected: NOTRUN
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue