diff options
author | Víctor Manuel Jáquez Leal <vjaquez@igalia.com> | 2018-08-02 14:09:45 +0200 |
---|---|---|
committer | Fernando Jiménez Moreno <ferjmoreno@gmail.com> | 2018-10-08 16:11:59 +0200 |
commit | ce76b5780a45a9e00ae3a235185d2ea15c6b688b (patch) | |
tree | 086ea8a7eb2fd5e9c05d2cec6da7b5ac337793c2 | |
parent | 0ff9ecc18ac0fadf45f2e64192fe2e1d86760806 (diff) | |
download | servo-ce76b5780a45a9e00ae3a235185d2ea15c6b688b.tar.gz servo-ce76b5780a45a9e00ae3a235185d2ea15c6b688b.zip |
dom: htmlmediaelement: add initial player bits
Also removes the usage of audio-video-metadata crate (?)
-rw-r--r-- | Cargo.lock | 55 | ||||
-rw-r--r-- | components/script/Cargo.toml | 1 | ||||
-rw-r--r-- | components/script/dom/htmlmediaelement.rs | 129 | ||||
-rw-r--r-- | components/script/lib.rs | 1 |
4 files changed, 101 insertions, 85 deletions
diff --git a/Cargo.lock b/Cargo.lock index 35444b693a6..8c7da7e5584 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,16 +98,6 @@ dependencies = [ ] [[package]] -name = "audio-video-metadata" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "mp3-metadata 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "mp4parse 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ogg_metadata 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] name = "azure" version = "0.34.0" source = "git+https://github.com/servo/rust-azure#b3c8ddc64f2760cfb5c29818c93b9a02fac50e5e" @@ -194,11 +184,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "bitreader" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] name = "block" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2242,22 +2227,6 @@ dependencies = [ ] [[package]] -name = "mp3-metadata" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "mp4parse" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] name = "msdos_time" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2498,23 +2467,6 @@ dependencies = [ ] [[package]] -name = "ogg" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ogg_metadata" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ogg 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] name = "openssl" version = "0.9.24" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2981,7 +2933,6 @@ name = "script" version = "0.0.1" dependencies = [ "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "audio-video-metadata 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4344,7 +4295,6 @@ dependencies = [ "checksum ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50" "checksum atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2dcb6e6d35f20276943cc04bb98e538b348d525a04ac79c10021561d202f21" "checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860" -"checksum audio-video-metadata 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3c23600291b35b9cd381f5cfca636f5d7d75e7d7192eddf867de84a6732cad5c" "checksum azure 0.34.0 (git+https://github.com/servo/rust-azure)" = "<none>" "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" @@ -4354,7 +4304,6 @@ dependencies = [ "checksum bindgen 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eac4ed5f2de9efc3c87cb722468fa49d0763e98f999d539bfc5e452c13d85c91" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" -"checksum bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80b13e2ab064ff3aa0bdbf1eff533f9822dc37899821f5f98c67f263eab51707" "checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" "checksum blurdroid 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "19b23557dd27704797128f9db2816416bef20dad62d4a9768714eeb65f07d296" "checksum blurmac 0.1.0 (git+https://github.com/servo/devices)" = "<none>" @@ -4519,8 +4468,6 @@ dependencies = [ "checksum mozangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "45a8a18a41cfab0fde25cc2f43ea89064d211a0fbb33225b8ff93ab20406e0e7" "checksum mozjs 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b9f85c1120b07d7a2acc9d1d62df1fe16f64162399448fb5307bf2bc3bd066c9" "checksum mozjs_sys 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ff07b0f0a2371dc08d75d55371ca311be67e1fdfa6c146fc8ad154c340f70c9" -"checksum mp3-metadata 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ab5f1d2693586420208d1200ce5a51cd44726f055b635176188137aff42c7de" -"checksum mp4parse 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7316728464443fe5793a805dde3257864e9690cf46374daff3ce93de1df2f254" "checksum msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aad9dfe950c057b1bfe9c1f2aa51583a8468ef2a5baba2ebbe06d775efeb7729" "checksum muldiv 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "451a9a05d2a32c566c897835e0ea95cf79ed2fdfe957924045a1721a36c9980f" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" @@ -4539,8 +4486,6 @@ dependencies = [ "checksum objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" "checksum objc_id 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4730aa1c64d722db45f7ccc4113a3e2c465d018de6db4d3e7dfe031e8c8a297" "checksum offscreen_gl_context 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "95f2e39e3b8c95495cfec835b6fefee3f1e7d63c6f81d99796b4f9926c02db3c" -"checksum ogg 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7137bf02687385302f4c0aecd77cfce052b69f5b4ee937be778e125c62f67e30" -"checksum ogg_metadata 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fc665717454399cba557c55ad226148996e9266ee291f8a37a98bb2cded0a490" "checksum openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "a3605c298474a3aa69de92d21139fb5e2a81688d308262359d85cdd0d12a7985" "checksum openssl-sys 0.9.27 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdc5c4a02e69ce65046f1763a0181107038e02176233acb0b3351d7cc588f9" "checksum ordered-float 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9a3c8db0fca1fdb34404f0b1286db252f23930b9f7a481e376c16c0d5c309d4" diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index 913edf25f2e..52108a89c59 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -30,7 +30,6 @@ tinyfiledialogs = "3.0" [dependencies] app_units = "0.7" -audio-video-metadata = "0.1.4" backtrace = {version = "0.3", optional = true} base64 = "0.6" bitflags = "1.0" diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index 6a89500e3fb..f726648f5d2 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -2,7 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use audio_video_metadata; use document_loader::{LoadBlocker, LoadType}; use dom::attr::Attr; use dom::bindings::cell::DomRefCell; @@ -40,6 +39,8 @@ use net_traits::{FetchResponseListener, FetchMetadata, Metadata, NetworkError}; use net_traits::request::{CredentialsMode, Destination, RequestInit}; use network_listener::{NetworkListener, PreInvoke}; use script_thread::ScriptThread; +use servo_media::player::{PlaybackState, Player, PlayerEvent}; +use servo_media::ServoMedia; use servo_url::ServoUrl; use std::cell::Cell; use std::collections::VecDeque; @@ -49,6 +50,8 @@ use std::sync::{Arc, Mutex}; use task_source::{TaskSource, TaskSourceName}; use time::{self, Timespec, Duration}; +unsafe_no_jsmanaged_fields!(Arc<Mutex<Box<Player>>>); + #[dom_struct] // FIXME(nox): A lot of tasks queued for this element should probably be in the // media element event task source. @@ -82,6 +85,10 @@ pub struct HTMLMediaElement { /// Play promises which are soon to be fulfilled by a queued task. #[ignore_malloc_size_of = "promises are hard"] in_flight_play_promises_queue: DomRefCell<VecDeque<(Box<[Rc<Promise>]>, ErrorResult)>>, + /// Whether the media metadata has been completely received. + have_metadata: Cell<bool>, + #[ignore_malloc_size_of = "servo_media"] + player: Arc<Mutex<Box<Player>>>, } /// <https://html.spec.whatwg.org/multipage/#dom-media-networkstate> @@ -122,6 +129,10 @@ impl HTMLMediaElement { delaying_the_load_event_flag: Default::default(), pending_play_promises: Default::default(), in_flight_play_promises_queue: Default::default(), + have_metadata: Cell::new(false), + player: Arc::new(Mutex::new( + ServoMedia::get().unwrap().create_player().unwrap(), + )), } } @@ -217,7 +228,9 @@ impl HTMLMediaElement { return; } - this.fulfill_in_flight_play_promises(|| ()); + this.fulfill_in_flight_play_promises(|| { + this.player.lock().unwrap().play(); + }); }), window.upcast(), ).unwrap(); @@ -263,6 +276,9 @@ impl HTMLMediaElement { // Step 2.3.2. this.upcast::<EventTarget>().fire_event(atom!("pause")); + //FIXME(victor) + //this.player.lock().unwrap().pause(); + // Step 2.3.3. // Done after running this closure in // `fulfill_in_flight_play_promises`. @@ -298,6 +314,7 @@ impl HTMLMediaElement { this.fulfill_in_flight_play_promises(|| { // Step 2.1. this.upcast::<EventTarget>().fire_event(atom!("playing")); + this.player.lock().unwrap().play(); // Step 2.2. // Done after running this closure in @@ -587,6 +604,7 @@ impl HTMLMediaElement { ..RequestInit::default() }; + self.setup_media_player(); let context = Arc::new(Mutex::new(HTMLMediaElementContext::new(self))); let (action_sender, action_receiver) = ipc::channel().unwrap(); let window = window_from_node(self); @@ -648,6 +666,8 @@ impl HTMLMediaElement { // Step 5. this.upcast::<EventTarget>().fire_event(atom!("error")); + this.player.lock().unwrap().stop(); + // Step 6. // Done after running this closure in // `fulfill_in_flight_play_promises`. @@ -806,6 +826,72 @@ impl HTMLMediaElement { } self.media_element_load_algorithm(); } + + // servo media player + fn setup_media_player(&self) { + let (action_sender, action_receiver) = ipc::channel().unwrap(); + + self.player + .lock() + .unwrap() + .register_event_handler(action_sender); + self.player.lock().unwrap().setup().unwrap(); + + let trusted_node = Trusted::new(self); + let window = window_from_node(self); + let task_source = window.dom_manipulation_task_source(); + let task_canceller = window.task_canceller(TaskSourceName::DOMManipulation); + ROUTER.add_route( + action_receiver.to_opaque(), + Box::new(move |message| { + let event: PlayerEvent = message.to().unwrap(); + let this = trusted_node.clone(); + task_source + .queue_with_canceller( + task!(handle_player_event: move || { + this.root().handle_player_event(&event); + }), + &task_canceller, + ).unwrap(); + }), + ); + } + + fn handle_player_event(&self, event: &PlayerEvent) { + match *event { + PlayerEvent::MetadataUpdated(ref metadata) => { + if !self.have_metadata.get() { + // 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 let Some(_dur) = metadata.duration { + // Setp 6. + self.change_ready_state(ReadyState::HaveMetadata); + self.have_metadata.set(true); + } + } else { + // => set the element's delaying-the-load-event flag to false + self.change_ready_state(ReadyState::HaveCurrentData); + } + } + PlayerEvent::StateChanged(ref state) => match *state { + PlaybackState::Paused => { + if self.ready_state.get() == ReadyState::HaveMetadata { + self.change_ready_state(ReadyState::HaveEnoughData); + } + } + _ => {} + }, + PlayerEvent::EndOfStream => {} + PlayerEvent::FrameUpdated => {} + PlayerEvent::Error => { + self.error.set(Some(&*MediaError::new( + &*window_from_node(self), + MEDIA_ERR_DECODE, + ))); + self.upcast::<EventTarget>().fire_event(atom!("error")); + } + } + } } impl HTMLMediaElementMethods for HTMLMediaElement { @@ -969,16 +1055,12 @@ enum Resource { 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, - /// Whether the media metadata has been completely received. - have_metadata: bool, /// True if this response is invalid and should be ignored. ignore_response: bool, } @@ -1012,22 +1094,17 @@ impl FetchResponseListener for HTMLMediaElementContext { } } - fn process_response_chunk(&mut self, mut payload: Vec<u8>) { + fn process_response_chunk(&mut self, payload: Vec<u8>) { if self.ignore_response { // An error was received previously, skip processing the payload. 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(ReadyState::HaveCurrentData); + // push input data into the player + if let Err(_) = elem.player.lock().unwrap().push_data(payload) { + eprintln!("Couldn't push input data to player"); } // https://html.spec.whatwg.org/multipage/#concept-media-load-resource step 4, @@ -1050,14 +1127,20 @@ impl FetchResponseListener for HTMLMediaElementContext { return; } let elem = self.elem.root(); + let player = elem.player.lock().unwrap(); + + // signal the eos to player + if let Err(_) = player.end_of_stream() { + eprintln!("Couldn't signal EOS to player"); + } // => "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 { + if !elem.have_metadata.get() { + // FIXME(victor): adjust player's max-size (or buffering) elem.queue_dedicated_media_source_failure_steps(); - } // => "Once the entire media resource has been fetched..." - else if status.is_ok() { + } else if status.is_ok() { elem.change_ready_state(ReadyState::HaveEnoughData); elem.upcast::<EventTarget>().fire_event(atom!("progress")); @@ -1100,20 +1183,10 @@ impl HTMLMediaElementContext { fn new(elem: &HTMLMediaElement) -> 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), - have_metadata: false, ignore_response: false, } } - - fn check_metadata(&mut self, elem: &HTMLMediaElement) { - if audio_video_metadata::get_format_from_slice(&self.data).is_ok() { - // Step 6. - elem.change_ready_state(ReadyState::HaveMetadata); - self.have_metadata = true; - } - } } diff --git a/components/script/lib.rs b/components/script/lib.rs index 097f69d7808..eda29279bae 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -18,7 +18,6 @@ )] extern crate app_units; -extern crate audio_video_metadata; #[cfg(any(feature = "webgl_backtrace", feature = "js_backtrace"))] extern crate backtrace; extern crate base64; |