HTMLMediaElement seeking

This commit is contained in:
Fernando Jiménez Moreno 2018-10-22 16:01:00 +02:00
parent 2db141fb8b
commit 75407822bc
5 changed files with 124 additions and 19 deletions

24
Cargo.lock generated
View file

@ -3025,7 +3025,7 @@ dependencies = [
"serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-media 0.1.0 (git+https://github.com/servo/media)",
"servo-media 0.1.0 (git+https://github.com/ferjm/media?branch=seek)",
"servo_allocator 0.0.1",
"servo_arc 0.1.1",
"servo_atoms 0.0.1",
@ -3261,9 +3261,9 @@ name = "servo-media"
version = "0.1.0"
source = "git+https://github.com/servo/media#3b347d7b0431c58611e2bd7b22d34062b64cda26"
dependencies = [
"servo-media-audio 0.1.0 (git+https://github.com/servo/media)",
"servo-media-gstreamer 0.1.0 (git+https://github.com/servo/media)",
"servo-media-player 0.1.0 (git+https://github.com/servo/media)",
"servo-media-audio 0.1.0 (git+https://github.com/ferjm/media?branch=seek)",
"servo-media-gstreamer 0.1.0 (git+https://github.com/ferjm/media?branch=seek)",
"servo-media-player 0.1.0 (git+https://github.com/ferjm/media?branch=seek)",
]
[[package]]
@ -3279,7 +3279,7 @@ dependencies = [
"petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
"servo_media_derive 0.1.0 (git+https://github.com/servo/media)",
"servo_media_derive 0.1.0 (git+https://github.com/ferjm/media?branch=seek)",
"smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -3296,8 +3296,8 @@ dependencies = [
"gstreamer-player 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-channel 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-media-audio 0.1.0 (git+https://github.com/servo/media)",
"servo-media-player 0.1.0 (git+https://github.com/servo/media)",
"servo-media-audio 0.1.0 (git+https://github.com/ferjm/media?branch=seek)",
"servo-media-player 0.1.0 (git+https://github.com/ferjm/media?branch=seek)",
"zip 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -4586,12 +4586,12 @@ dependencies = [
"checksum servo-fontconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93f799b649b4a2bf362398910eca35240704c7e765e780349b2bb1070d892262"
"checksum servo-fontconfig-sys 4.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b46d201addcfbd25c1798ad1281d98c40743824e0b0f1e611bd3d5d0d31a7b8d"
"checksum servo-freetype-sys 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d00ab791f66cd2ec58e72c91b6076cee20fac560463aa871404eb31dfc9c4ff"
"checksum servo-media 0.1.0 (git+https://github.com/servo/media)" = "<none>"
"checksum servo-media-audio 0.1.0 (git+https://github.com/servo/media)" = "<none>"
"checksum servo-media-gstreamer 0.1.0 (git+https://github.com/servo/media)" = "<none>"
"checksum servo-media-player 0.1.0 (git+https://github.com/servo/media)" = "<none>"
"checksum servo-media 0.1.0 (git+https://github.com/ferjm/media?branch=seek)" = "<none>"
"checksum servo-media-audio 0.1.0 (git+https://github.com/ferjm/media?branch=seek)" = "<none>"
"checksum servo-media-gstreamer 0.1.0 (git+https://github.com/ferjm/media?branch=seek)" = "<none>"
"checksum servo-media-player 0.1.0 (git+https://github.com/ferjm/media?branch=seek)" = "<none>"
"checksum servo-skia 0.30000019.1 (registry+https://github.com/rust-lang/crates.io-index)" = "82eddddcf9512dd7c60eccdb486e60e5bd4930afaa4da2d7d4afdff75950fb88"
"checksum servo_media_derive 0.1.0 (git+https://github.com/servo/media)" = "<none>"
"checksum servo_media_derive 0.1.0 (git+https://github.com/ferjm/media?branch=seek)" = "<none>"
"checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c"
"checksum shared_library 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8254bf098ce4d8d7cc7cc6de438c5488adc5297e5b7ffef88816c0a91bd289c1"
"checksum sig 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c6649e43c1a1e68d29ed56d0dc3b5b6cf3b901da77cf107c4066b9e3da036df5"

View file

@ -22,3 +22,5 @@ opt-level = 3
#
# [patch."https://github.com/servo/<repository>"]
# <crate> = { path = "/path/to/local/checkout" }
[patch."https://github.com/servo/media"]
servo-media = { git = "https://github.com/ferjm/media", branch = "seek" }

View file

@ -74,6 +74,8 @@ scan
screen
scroll-position
search
seeked
seeking
select
serif
statechange

View file

@ -170,10 +170,12 @@ pub struct HTMLMediaElement {
show_poster: Cell<bool>,
/// https://html.spec.whatwg.org/multipage/#dom-media-duration
duration: Cell<f64>,
/// https://html.spec.whatwg.org/multipage/media.html#official-playback-position
/// https://html.spec.whatwg.org/multipage/#official-playback-position
playback_position: Cell<f64>,
/// https://html.spec.whatwg.org/multipage/media.html#default-playback-start-position
/// https://html.spec.whatwg.org/multipage/#default-playback-start-position
default_playback_start_position: Cell<f64>,
/// https://html.spec.whatwg.org/multipage/#dom-media-seeking
seeking: Cell<bool>,
}
/// <https://html.spec.whatwg.org/multipage/#dom-media-networkstate>
@ -223,6 +225,7 @@ impl HTMLMediaElement {
duration: Cell::new(f64::NAN),
playback_position: Cell::new(0.),
default_playback_start_position: Cell::new(0.),
seeking: Cell::new(false),
}
}
@ -969,8 +972,69 @@ impl HTMLMediaElement {
}
// https://html.spec.whatwg.org/multipage/#dom-media-seek
fn seek(&self, _time: f64, _approximate_for_speed: bool) {
// XXX
fn seek(&self, time: f64, approximate_for_speed: bool) {
// Step 1.
self.show_poster.set(false);
// Step 2.
if self.ready_state.get() == ReadyState::HaveNothing {
return;
}
// Step 3.
if self.seeking.get() {
// This will cancel only the sync part of the seek algorithm.
self.generation_id.set(self.generation_id.get() + 1);
}
// Step 4.
// The flag will be cleared when the media engine tells us the seek was done.
self.seeking.set(true);
// Step 5.
// XXX(ferjm) The rest of the steps should be run in parallel, so seeking cancelation
// can be done properly. No other browser does it yet anyway.
// Step 6.
let time = f64::min(time, self.Duration());
// Step 7.
let time = f64::max(time, 0.);
// Step 8.
// XXX(ferjm) seekable attribute.
// Step 9.
let accurate = !approximate_for_speed;
// Step 10.
let window = window_from_node(self);
let task_source = window.media_element_task_source();
task_source.queue_simple_event(self.upcast(), atom!("seeking"), &window);
// Step 11.
// XXX self.player.seek(time, accurate);
// The rest of the steps are handled when the media engine signals a
// ready state change or otherwise satisfies seek completion and signals
// a position change.
}
// https://html.spec.whatwg.org/multipage/#dom-media-seek
fn seek_sync(&self) {
// Step 14.
self.seeking.set(false);
// Step 15.
self.time_marches_on();
// Step 16.
let window = window_from_node(self);
let task_source = window.media_element_task_source();
task_source.queue_simple_event(self.upcast(), atom!("timeupdate"), &window);
// Step 17.
task_source.queue_simple_event(self.upcast(), atom!("seeked"), &window);
}
fn setup_media_player(&self) -> Result<(), ServoMediaError> {
@ -1043,7 +1107,10 @@ impl HTMLMediaElement {
// Step 8.
if self.default_playback_start_position.get() > 0. {
self.seek(self.default_playback_start_position.get(), /* approximate_for_speed*/ false);
self.seek(
self.default_playback_start_position.get(),
/* approximate_for_speed*/ false,
);
_jumped = true;
}
@ -1084,6 +1151,20 @@ impl HTMLMediaElement {
PlayerEvent::FrameUpdated => {
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
},
PlayerEvent::SeekData(_) => {
// XXX byte-range request
},
PlayerEvent::SeekDone(_) => {
// Continuation of
// https://html.spec.whatwg.org/multipage/#dom-media-seek
// Step 13.
let task = MediaElementMicrotask::SeekedTask {
elem: DomRoot::from_ref(self),
generation_id: self.generation_id.get(),
};
ScriptThread::await_stable_state(Microtask::MediaElement(task));
},
PlayerEvent::Error => {
self.error.set(Some(&*MediaError::new(
&*window_from_node(self),
@ -1206,6 +1287,14 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
self.seek(*time, /* approximate_for_speed */ false);
}
}
fn Seeking(&self) -> bool {
self.seeking.get()
}
fn FastSeek(&self, time: Finite<f64>) {
self.seek(*time, /* approximat_for_speed */ true);
}
}
impl VirtualMethods for HTMLMediaElement {
@ -1263,6 +1352,10 @@ pub enum MediaElementMicrotask {
PauseIfNotInDocumentTask {
elem: DomRoot<HTMLMediaElement>,
},
SeekedTask {
elem: DomRoot<HTMLMediaElement>,
generation_id: u32,
},
}
impl MicrotaskRunnable for MediaElementMicrotask {
@ -1282,6 +1375,14 @@ impl MicrotaskRunnable for MediaElementMicrotask {
elem.internal_pause_steps();
}
},
&MediaElementMicrotask::SeekedTask {
ref elem,
generation_id,
} => {
if generation_id == elem.generation_id.get() {
elem.seek_sync();
}
},
}
}
}

View file

@ -34,11 +34,11 @@ interface HTMLMediaElement : HTMLElement {
const unsigned short HAVE_FUTURE_DATA = 3;
const unsigned short HAVE_ENOUGH_DATA = 4;
readonly attribute unsigned short readyState;
// readonly attribute boolean seeking;
readonly attribute boolean seeking;
// playback state
attribute double currentTime;
// void fastSeek(double time);
void fastSeek(double time);
readonly attribute unrestricted double duration;
// Date getStartDate();
readonly attribute boolean paused;