mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
media element: support seekable attribute (#36541)
support seekable attribute in `htmlmediaelement`, modify `seek` algorithm to use `seekable` attribute. related [specs](https://html.spec.whatwg.org/multipage/media.html#dom-media-seekable) Testing: Run WPT Test Fixes: https://github.com/servo/servo/issues/22297 Will wait for https://github.com/servo/media/pull/435 before turning this to ready for review. cc @jdm @xiaochengh Signed-off-by: rayguo17 <rayguo17@gmail.com>
This commit is contained in:
parent
15199ba2ef
commit
f5e6eb289a
5 changed files with 59 additions and 39 deletions
24
Cargo.lock
generated
24
Cargo.lock
generated
|
@ -6600,7 +6600,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo-media"
|
name = "servo-media"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/media#c7eab1ae326b8b95b938741660553342f7cd94b7"
|
source = "git+https://github.com/servo/media#eb96030cdd153ebcbbe3836dc6471303187740e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"servo-media-audio",
|
"servo-media-audio",
|
||||||
|
@ -6613,7 +6613,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo-media-audio"
|
name = "servo-media-audio"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/servo/media#c7eab1ae326b8b95b938741660553342f7cd94b7"
|
source = "git+https://github.com/servo/media#eb96030cdd153ebcbbe3836dc6471303187740e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byte-slice-cast",
|
"byte-slice-cast",
|
||||||
"euclid",
|
"euclid",
|
||||||
|
@ -6634,7 +6634,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo-media-derive"
|
name = "servo-media-derive"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/media#c7eab1ae326b8b95b938741660553342f7cd94b7"
|
source = "git+https://github.com/servo/media#eb96030cdd153ebcbbe3836dc6471303187740e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -6644,7 +6644,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo-media-dummy"
|
name = "servo-media-dummy"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/media#c7eab1ae326b8b95b938741660553342f7cd94b7"
|
source = "git+https://github.com/servo/media#eb96030cdd153ebcbbe3836dc6471303187740e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ipc-channel",
|
"ipc-channel",
|
||||||
"servo-media",
|
"servo-media",
|
||||||
|
@ -6658,7 +6658,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo-media-gstreamer"
|
name = "servo-media-gstreamer"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/media#c7eab1ae326b8b95b938741660553342f7cd94b7"
|
source = "git+https://github.com/servo/media#eb96030cdd153ebcbbe3836dc6471303187740e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byte-slice-cast",
|
"byte-slice-cast",
|
||||||
"glib",
|
"glib",
|
||||||
|
@ -6691,7 +6691,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo-media-gstreamer-render"
|
name = "servo-media-gstreamer-render"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/media#c7eab1ae326b8b95b938741660553342f7cd94b7"
|
source = "git+https://github.com/servo/media#eb96030cdd153ebcbbe3836dc6471303187740e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gstreamer",
|
"gstreamer",
|
||||||
"gstreamer-video",
|
"gstreamer-video",
|
||||||
|
@ -6701,7 +6701,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo-media-gstreamer-render-android"
|
name = "servo-media-gstreamer-render-android"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/media#c7eab1ae326b8b95b938741660553342f7cd94b7"
|
source = "git+https://github.com/servo/media#eb96030cdd153ebcbbe3836dc6471303187740e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glib",
|
"glib",
|
||||||
"gstreamer",
|
"gstreamer",
|
||||||
|
@ -6715,7 +6715,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo-media-gstreamer-render-unix"
|
name = "servo-media-gstreamer-render-unix"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/media#c7eab1ae326b8b95b938741660553342f7cd94b7"
|
source = "git+https://github.com/servo/media#eb96030cdd153ebcbbe3836dc6471303187740e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glib",
|
"glib",
|
||||||
"gstreamer",
|
"gstreamer",
|
||||||
|
@ -6730,7 +6730,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo-media-player"
|
name = "servo-media-player"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/media#c7eab1ae326b8b95b938741660553342f7cd94b7"
|
source = "git+https://github.com/servo/media#eb96030cdd153ebcbbe3836dc6471303187740e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ipc-channel",
|
"ipc-channel",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -6742,7 +6742,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo-media-streams"
|
name = "servo-media-streams"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/media#c7eab1ae326b8b95b938741660553342f7cd94b7"
|
source = "git+https://github.com/servo/media#eb96030cdd153ebcbbe3836dc6471303187740e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
@ -6750,12 +6750,12 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo-media-traits"
|
name = "servo-media-traits"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/media#c7eab1ae326b8b95b938741660553342f7cd94b7"
|
source = "git+https://github.com/servo/media#eb96030cdd153ebcbbe3836dc6471303187740e9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo-media-webrtc"
|
name = "servo-media-webrtc"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/servo/media#c7eab1ae326b8b95b938741660553342f7cd94b7"
|
source = "git+https://github.com/servo/media#eb96030cdd153ebcbbe3836dc6471303187740e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"servo-media-streams",
|
"servo-media-streams",
|
||||||
|
|
|
@ -29,6 +29,7 @@ use net_traits::{
|
||||||
ResourceTimingType,
|
ResourceTimingType,
|
||||||
};
|
};
|
||||||
use pixels::Image;
|
use pixels::Image;
|
||||||
|
use script_bindings::codegen::GenericBindings::TimeRangesBinding::TimeRangesMethods;
|
||||||
use script_bindings::codegen::InheritTypes::{
|
use script_bindings::codegen::InheritTypes::{
|
||||||
ElementTypeId, HTMLElementTypeId, HTMLMediaElementTypeId, NodeTypeId,
|
ElementTypeId, HTMLElementTypeId, HTMLMediaElementTypeId, NodeTypeId,
|
||||||
};
|
};
|
||||||
|
@ -1277,15 +1278,40 @@ impl HTMLMediaElement {
|
||||||
let time = f64::max(time, 0.);
|
let time = f64::max(time, 0.);
|
||||||
|
|
||||||
// Step 8.
|
// Step 8.
|
||||||
// XXX(ferjm) seekable attribute: we need to get the information about
|
let seekable = self.Seekable();
|
||||||
// what's been decoded and buffered so far from servo-media
|
if seekable.Length() == 0 {
|
||||||
// and add the seekable attribute as a TimeRange.
|
self.seeking.set(false);
|
||||||
if let Some(ref current_fetch_context) = *self.current_fetch_context.borrow() {
|
return;
|
||||||
if !current_fetch_context.is_seekable() {
|
}
|
||||||
self.seeking.set(false);
|
let mut nearest_seekable_position = 0.0;
|
||||||
return;
|
let mut in_seekable_range = false;
|
||||||
|
let mut nearest_seekable_distance = f64::MAX;
|
||||||
|
for i in 0..seekable.Length() {
|
||||||
|
let start = seekable.Start(i).unwrap().abs();
|
||||||
|
let end = seekable.End(i).unwrap().abs();
|
||||||
|
if time >= start && time <= end {
|
||||||
|
nearest_seekable_position = time;
|
||||||
|
in_seekable_range = true;
|
||||||
|
break;
|
||||||
|
} else if time < start {
|
||||||
|
let distance = start - time;
|
||||||
|
if distance < nearest_seekable_distance {
|
||||||
|
nearest_seekable_distance = distance;
|
||||||
|
nearest_seekable_position = start;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let distance = time - end;
|
||||||
|
if distance < nearest_seekable_distance {
|
||||||
|
nearest_seekable_distance = distance;
|
||||||
|
nearest_seekable_position = end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let time = if in_seekable_range {
|
||||||
|
time
|
||||||
|
} else {
|
||||||
|
nearest_seekable_position
|
||||||
|
};
|
||||||
|
|
||||||
// Step 9.
|
// Step 9.
|
||||||
// servo-media with gstreamer does not support inaccurate seeking for now.
|
// servo-media with gstreamer does not support inaccurate seeking for now.
|
||||||
|
@ -2402,6 +2428,19 @@ impl HTMLMediaElementMethods<crate::DomTypeHolder> for HTMLMediaElement {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-media-seekable
|
||||||
|
fn Seekable(&self) -> DomRoot<TimeRanges> {
|
||||||
|
let mut seekable = TimeRangesContainer::default();
|
||||||
|
if let Some(ref player) = *self.player.borrow() {
|
||||||
|
if let Ok(ranges) = player.lock().unwrap().seekable() {
|
||||||
|
for range in ranges {
|
||||||
|
let _ = seekable.add(range.start, range.end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TimeRanges::new(self.global().as_window(), seekable, CanGc::note())
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-media-buffered
|
// https://html.spec.whatwg.org/multipage/#dom-media-buffered
|
||||||
fn Buffered(&self) -> DomRoot<TimeRanges> {
|
fn Buffered(&self) -> DomRoot<TimeRanges> {
|
||||||
let mut buffered = TimeRangesContainer::default();
|
let mut buffered = TimeRangesContainer::default();
|
||||||
|
|
|
@ -45,7 +45,7 @@ interface HTMLMediaElement : HTMLElement {
|
||||||
[Throws] attribute double defaultPlaybackRate;
|
[Throws] attribute double defaultPlaybackRate;
|
||||||
[Throws] attribute double playbackRate;
|
[Throws] attribute double playbackRate;
|
||||||
readonly attribute TimeRanges played;
|
readonly attribute TimeRanges played;
|
||||||
// readonly attribute TimeRanges seekable;
|
readonly attribute TimeRanges seekable;
|
||||||
readonly attribute boolean ended;
|
readonly attribute boolean ended;
|
||||||
[CEReactions] attribute boolean autoplay;
|
[CEReactions] attribute boolean autoplay;
|
||||||
[CEReactions] attribute boolean loop;
|
[CEReactions] attribute boolean loop;
|
||||||
|
|
|
@ -2322,9 +2322,6 @@
|
||||||
[HTMLSelectElement interface: document.createElement("select") must inherit property "autocomplete" with the proper type]
|
[HTMLSelectElement interface: document.createElement("select") must inherit property "autocomplete" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLMediaElement interface: attribute seekable]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLTableSectionElement interface: attribute align]
|
[HTMLTableSectionElement interface: attribute align]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -6487,36 +6484,24 @@
|
||||||
[HTMLMediaElement interface: document.createElement("video") must inherit property "preservesPitch" with the proper type]
|
[HTMLMediaElement interface: document.createElement("video") must inherit property "preservesPitch" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLMediaElement interface: document.createElement("video") must inherit property "seekable" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLMediaElement interface: document.createElement("audio") must inherit property "getStartDate()" with the proper type]
|
[HTMLMediaElement interface: document.createElement("audio") must inherit property "getStartDate()" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLMediaElement interface: document.createElement("audio") must inherit property "preservesPitch" with the proper type]
|
[HTMLMediaElement interface: document.createElement("audio") must inherit property "preservesPitch" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLMediaElement interface: document.createElement("audio") must inherit property "seekable" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLMediaElement interface: new Audio() must inherit property "getStartDate()" with the proper type]
|
[HTMLMediaElement interface: new Audio() must inherit property "getStartDate()" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLMediaElement interface: new Audio() must inherit property "preservesPitch" with the proper type]
|
[HTMLMediaElement interface: new Audio() must inherit property "preservesPitch" with the proper type]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLMediaElement interface: new Audio() must inherit property "seekable" with the proper type]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLMediaElement interface: operation getStartDate()]
|
[HTMLMediaElement interface: operation getStartDate()]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLMediaElement interface: attribute preservesPitch]
|
[HTMLMediaElement interface: attribute preservesPitch]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLMediaElement interface: attribute seekable]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLMapElement interface: attribute name]
|
[HTMLMapElement interface: attribute name]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
[seek-to-currentTime.html]
|
|
||||||
[seek to currentTime]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue