Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement srcObject logic for Blob media providers #23103

Merged
merged 1 commit into from Apr 3, 2019
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Implement srcObject logic for Blob media providers

  • Loading branch information
ferjm committed Mar 27, 2019
commit d15640081cadbdb8c26a4ba0fdc8c39742ffbdcc
@@ -17,13 +17,15 @@ use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorMethod
use crate::dom::bindings::codegen::Bindings::TextTrackBinding::{TextTrackKind, TextTrackMode};
use crate::dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementTypeId};
use crate::dom::bindings::codegen::InheritTypes::{HTMLMediaElementTypeId, NodeTypeId};
use crate::dom::bindings::codegen::UnionTypes::VideoTrackOrAudioTrackOrTextTrack;
use crate::dom::bindings::codegen::UnionTypes::{
MediaStreamOrBlob, VideoTrackOrAudioTrackOrTextTrack,
};
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::num::Finite;
use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::{DomRoot, LayoutDom, MutNullableDom};
use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom};
use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::blob::Blob;
use crate::dom::document::Document;
@@ -35,13 +37,15 @@ use crate::dom::htmlelement::HTMLElement;
use crate::dom::htmlsourceelement::HTMLSourceElement;
use crate::dom::htmlvideoelement::HTMLVideoElement;
use crate::dom::mediaerror::MediaError;
use crate::dom::mediastream::MediaStream;
use crate::dom::node::{document_from_node, window_from_node, Node, NodeDamage, UnbindContext};
use crate::dom::performanceresourcetiming::InitiatorType;
use crate::dom::promise::Promise;
use crate::dom::texttrack::TextTrack;
use crate::dom::texttracklist::TextTrackList;
use crate::dom::timeranges::{TimeRanges, TimeRangesContainer};
use crate::dom::trackevent::TrackEvent;
use crate::dom::url::URL;
use crate::dom::videotrack::VideoTrack;
use crate::dom::videotracklist::VideoTrackList;
use crate::dom::virtualmethods::VirtualMethods;
@@ -156,6 +160,25 @@ impl FrameRenderer for MediaFrameRenderer {
}
}

#[must_root]
#[derive(JSTraceable, MallocSizeOf)]
enum SrcObject {
MediaStream(Dom<MediaStream>),
Blob(Dom<Blob>),
}

impl From<MediaStreamOrBlob> for SrcObject {
#[allow(unrooted_must_root)]
fn from(src_object: MediaStreamOrBlob) -> SrcObject {
match src_object {
MediaStreamOrBlob::Blob(blob) => SrcObject::Blob(Dom::from_ref(&*blob)),
MediaStreamOrBlob::MediaStream(stream) => {
SrcObject::MediaStream(Dom::from_ref(&*stream))
},
}
}
}

#[dom_struct]
pub struct HTMLMediaElement {
htmlelement: HTMLElement,
@@ -164,7 +187,7 @@ pub struct HTMLMediaElement {
/// <https://html.spec.whatwg.org/multipage/#dom-media-readystate>
ready_state: Cell<ReadyState>,
/// <https://html.spec.whatwg.org/multipage/#dom-media-srcobject>
src_object: MutNullableDom<Blob>,
src_object: DomRefCell<Option<SrcObject>>,
/// <https://html.spec.whatwg.org/multipage/#dom-media-currentsrc>
current_src: DomRefCell<String>,
/// Incremented whenever tasks associated with this element are cancelled.
@@ -211,6 +234,9 @@ pub struct HTMLMediaElement {
muted: Cell<bool>,
/// URL of the media resource, if any.
resource_url: DomRefCell<Option<ServoUrl>>,
/// URL of the media resource, if the resource is set through the src_object attribute and it
/// is a blob.
blob_url: DomRefCell<Option<ServoUrl>>,
/// https://html.spec.whatwg.org/multipage/#dom-media-played
#[ignore_malloc_size_of = "Rc"]
played: DomRefCell<TimeRangesContainer>,
@@ -280,6 +306,7 @@ impl HTMLMediaElement {
volume: Cell::new(1.0),
seeking: Cell::new(false),
resource_url: DomRefCell::new(None),
blob_url: DomRefCell::new(None),
played: DomRefCell::new(TimeRangesContainer::new()),
audio_tracks_list: Default::default(),
video_tracks_list: Default::default(),
@@ -557,7 +584,7 @@ impl HTMLMediaElement {
Children(DomRoot<HTMLSourceElement>),
}
fn mode(media: &HTMLMediaElement) -> Option<Mode> {
if media.src_object.get().is_some() {
if media.src_object.borrow().is_some() {
return Some(Mode::Object);
}
if let Some(attr) = media
@@ -661,7 +688,7 @@ impl HTMLMediaElement {
}

fn fetch_request(&self, offset: Option<u64>) {
if self.resource_url.borrow().is_none() {
if self.resource_url.borrow().is_none() && self.blob_url.borrow().is_none() {
eprintln!("Missing request url");
self.queue_dedicated_media_source_failure_steps();
return;
@@ -679,8 +706,12 @@ impl HTMLMediaElement {
header::RANGE,
HeaderValue::from_str(&format!("bytes={}-", offset.unwrap_or(0))).unwrap(),
);
let url = match self.resource_url.borrow().as_ref() {
Some(url) => url.clone(),
None => self.blob_url.borrow().as_ref().unwrap().clone(),
};
let request = RequestInit {
url: self.resource_url.borrow().as_ref().unwrap().clone(),
url: url.clone(),
headers,
destination,
credentials_mode: CredentialsMode::Include,
@@ -700,7 +731,7 @@ impl HTMLMediaElement {
*current_fetch_context = Some(fetch_context);
let fetch_listener = Arc::new(Mutex::new(HTMLMediaElementFetchListener::new(
self,
self.resource_url.borrow().as_ref().unwrap().clone(),
url.clone(),
offset.unwrap_or(0),
)));
let (action_sender, action_receiver) = ipc::channel().unwrap();
@@ -788,8 +819,19 @@ impl HTMLMediaElement {
self.fetch_request(None);
},
Resource::Object => {
// FIXME(nox): Actually do something with the object.
self.queue_dedicated_media_source_failure_steps();
if let Some(ref src_object) = *self.src_object.borrow() {
match src_object {
SrcObject::Blob(blob) => {
let blob_url = URL::CreateObjectURL(&self.global(), &*blob);
*self.blob_url.borrow_mut() =
Some(ServoUrl::parse(&blob_url).expect("infallible"));
self.fetch_request(None);
},
SrcObject::MediaStream(_) => {
self.queue_dedicated_media_source_failure_steps();
},
}
}
},
}
}
@@ -1550,13 +1592,21 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
}

// https://html.spec.whatwg.org/multipage/#dom-media-srcobject
fn GetSrcObject(&self) -> Option<DomRoot<Blob>> {
self.src_object.get()
fn GetSrcObject(&self) -> Option<MediaStreamOrBlob> {
match *self.src_object.borrow() {
Some(ref src_object) => Some(match src_object {
SrcObject::Blob(blob) => MediaStreamOrBlob::Blob(DomRoot::from_ref(&*blob)),
SrcObject::MediaStream(stream) => {
MediaStreamOrBlob::MediaStream(DomRoot::from_ref(&*stream))
},
}),
None => None,
}
}

// https://html.spec.whatwg.org/multipage/#dom-media-srcobject
fn SetSrcObject(&self, value: Option<&Blob>) {
self.src_object.set(value);
fn SetSrcObject(&self, value: Option<MediaStreamOrBlob>) {
*self.src_object.borrow_mut() = value.map(|value| value.into());
self.media_element_load_algorithm();
}

@@ -5,7 +5,7 @@
// https://html.spec.whatwg.org/multipage/#htmlmediaelement

enum CanPlayTypeResult { "" /* empty string */, "maybe", "probably" };
typedef /* (MediaStream or MediaSource or */ Blob /* ) */ MediaProvider;
typedef (MediaStream /*or MediaSource */ or Blob) MediaProvider;

[Abstract]
interface HTMLMediaElement : HTMLElement {
@@ -1,5 +1,8 @@
{
"items": {
"conformancechecker": {
"html/semantics/embedded-content/media-elements/src_object_blob.html": []
},
"manual": {
"2dcontext/conformance-requirements/2d.coordinatespace-manual.html": [
[
{}
]
],
"html/semantics/embedded-content/media-elements/src_object_blob.html": [],
"html/semantics/embedded-content/media-elements/video_controls_present-manual.html": [
[
"html/semantics/embedded-content/media-elements/video_controls_present-manual.html",
{}
]
],
"html/semantics/embedded-content/media-elements/src_object_blob.html": [],
"html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-added.html": [
[
"html/semantics/embedded-content/media-elements/track/track-element/track-cue-rendering-after-controls-added.html",
{}
]
],
"html/semantics/embedded-content/media-elements/src_object_blob.html": [],
"infrastructure/assumptions/ahem-ref.html": [
[
"infrastructure/assumptions/ahem-ref.html",
]
},
"stub": {
"html/semantics/embedded-content/media-elements/src_object_blob.html": [],
"service-workers/stub-3.1-service-worker-obj.html": [
[
"service-workers/stub-3.1-service-worker-obj.html",
{}
]
],
"html/semantics/embedded-content/media-elements/src_object_blob.html": [],
"html/semantics/embedded-content/media-elements/track/track-element/cors/support/common.js": [
[
{}
{}
]
],
"html/semantics/embedded-content/media-elements/src_object_blob.html": [
[
"html/semantics/embedded-content/media-elements/src_object_blob.html",
{}
]
],
"html/semantics/embedded-content/media-elements/src_reflects_attribute_not_source_elements.html": [
[
"html/semantics/embedded-content/media-elements/src_reflects_attribute_not_source_elements.html",
{}
]
],
"html/semantics/embedded-content/media-elements/src_object_blob.html": [],
"svg/text/visualtests/text-inline-size-001-visual.svg": [
[
"svg/text/visualtests/text-inline-size-001-visual.svg",
]
},
"wdspec": {
"html/semantics/embedded-content/media-elements/src_object_blob.html": [],
"infrastructure/webdriver/tests/test_load_file.py": [
[
"infrastructure/webdriver/tests/test_load_file.py",
"56a99028deb273359f32fc14b53b9317a4b9c76d",
"testharness"
],
"html/semantics/embedded-content/media-elements/src_object_blob.html": [
"481a8184ea2fdc6220b147d43a653ed510cfd104",
"testharness"
],
"html/semantics/embedded-content/media-elements/src_reflects_attribute_not_source_elements.html": [
"3dd43cc3f5524a32b7438e33481552653076cbe8",
"testharness"
@@ -0,0 +1,31 @@
<!doctype html>
<meta charset="utf-8">
<title>HTMLMediaElement.srcObject blob</title>
<script src='/common/media.js'></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<video></video>
<script>
async_test(function(t) {
t.step(function() {
fetch(getVideoURI('/media/movie_5'))
.then(function(response) {
return response.blob();
})
.then(function(blob) {
let video = document.querySelector("video");
video.srcObject = blob;
video.addEventListener('ended', function() {
t.done();
});
video.play().catch(function(error) {
assert(false, error);
});
})
.catch(function(error) {
assert(false, error);
});
});
});
</script>

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.