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

Receive streams in WebRTC (and MediaStreamTrack support) #23342

Merged
merged 12 commits into from May 9, 2019

Some generated files are not rendered by default. Learn more.

@@ -108,6 +108,7 @@ text
time
timeupdate
toggle
track
transitionend
unhandledrejection
unload
@@ -105,6 +105,7 @@ use servo_media::audio::panner_node::{DistanceModel, PanningModel};
use servo_media::audio::param::ParamType;
use servo_media::player::Player;
use servo_media::streams::registry::MediaStreamId;
use servo_media::streams::MediaStreamType;
use servo_media::webrtc::WebRtcController;
use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
use smallvec::SmallVec;
@@ -490,7 +491,7 @@ unsafe_no_jsmanaged_fields!(NodeId);
unsafe_no_jsmanaged_fields!(AnalysisEngine, DistanceModel, PanningModel, ParamType);
unsafe_no_jsmanaged_fields!(dyn Player);
unsafe_no_jsmanaged_fields!(WebRtcController);
unsafe_no_jsmanaged_fields!(MediaStreamId);
unsafe_no_jsmanaged_fields!(MediaStreamId, MediaStreamType);
unsafe_no_jsmanaged_fields!(Mutex<MediaFrameRenderer>);
unsafe_no_jsmanaged_fields!(RenderApiSender);
unsafe_no_jsmanaged_fields!(ResourceFetchTiming);
@@ -840,9 +840,13 @@ impl HTMLMediaElement {
self.fetch_request(None);
},
SrcObject::MediaStream(ref stream) => {
for stream in stream.get_tracks() {
if let Err(_) =
self.player.borrow().as_ref().unwrap().set_stream(&stream)
for stream in &*stream.get_tracks() {
if let Err(_) = self
.player
.borrow()
.as_ref()
.unwrap()
.set_stream(&stream.id())
{
self.queue_dedicated_media_source_failure_steps();
}
@@ -14,9 +14,11 @@ use crate::dom::bindings::root::DomRoot;
use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope;
use crate::dom::mediastream::MediaStream;
use crate::dom::mediastreamtrack::MediaStreamTrack;
use crate::dom::promise::Promise;
use dom_struct::dom_struct;
use servo_media::streams::capture::{Constrain, ConstrainRange, MediaTrackConstraintSet};
use servo_media::streams::MediaStreamType;
use servo_media::ServoMedia;
use std::rc::Rc;

@@ -51,18 +53,20 @@ impl MediaDevicesMethods for MediaDevices {
InCompartment::Already(&in_compartment_proof),
);
let media = ServoMedia::get().unwrap();
let mut tracks = vec![];
let stream = MediaStream::new(&self.global());
if let Some(constraints) = convert_constraints(&constraints.audio) {
if let Some(audio) = media.create_audioinput_stream(constraints) {
tracks.push(audio)
let track = MediaStreamTrack::new(&self.global(), audio, MediaStreamType::Audio);
stream.add_track(&track);
}
}
if let Some(constraints) = convert_constraints(&constraints.video) {
if let Some(video) = media.create_videoinput_stream(constraints) {
tracks.push(video)
let track = MediaStreamTrack::new(&self.global(), video, MediaStreamType::Video);
stream.add_track(&track);
}
}
let stream = MediaStream::new(&self.global(), tracks);

p.resolve_native(&stream);
p
}
@@ -3,38 +3,131 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::MediaStreamBinding;
use crate::dom::bindings::reflector::reflect_dom_object;
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::codegen::Bindings::MediaStreamBinding::{self, MediaStreamMethods};
use crate::dom::bindings::error::Fallible;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString;
use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope;
use crate::dom::mediastreamtrack::MediaStreamTrack;
use crate::dom::window::Window;
use dom_struct::dom_struct;
use servo_media::streams::registry::MediaStreamId;
use servo_media::streams::MediaStreamType;
use std::cell::Ref;

#[dom_struct]
pub struct MediaStream {
eventtarget: EventTarget,
#[ignore_malloc_size_of = "defined in servo-media"]
tracks: DomRefCell<Vec<MediaStreamId>>,
tracks: DomRefCell<Vec<Dom<MediaStreamTrack>>>,
}

impl MediaStream {
pub fn new_inherited(tracks: Vec<MediaStreamId>) -> MediaStream {
pub fn new_inherited() -> MediaStream {
MediaStream {
eventtarget: EventTarget::new_inherited(),
tracks: DomRefCell::new(tracks),
tracks: DomRefCell::new(vec![]),
}
}

pub fn new(global: &GlobalScope, tracks: Vec<MediaStreamId>) -> DomRoot<MediaStream> {
pub fn new(global: &GlobalScope) -> DomRoot<MediaStream> {
reflect_dom_object(
Box::new(MediaStream::new_inherited(tracks)),
Box::new(MediaStream::new_inherited()),
global,
MediaStreamBinding::Wrap,
)
}

pub fn get_tracks(&self) -> Vec<MediaStreamId> {
self.tracks.borrow_mut().clone()
pub fn Constructor(global: &Window) -> Fallible<DomRoot<MediaStream>> {
Ok(MediaStream::new(&global.global()))
}

pub fn Constructor_(_: &Window, stream: &MediaStream) -> Fallible<DomRoot<MediaStream>> {
Ok(stream.Clone())
}

pub fn Constructor__(
global: &Window,
tracks: Vec<DomRoot<MediaStreamTrack>>,
) -> Fallible<DomRoot<MediaStream>> {
let new = MediaStream::new(&global.global());
for track in tracks {
// this is quadratic, but shouldn't matter much
// if this becomes a problem we can use a hash map
new.AddTrack(&track)
}
Ok(new)
}

pub fn get_tracks(&self) -> Ref<[Dom<MediaStreamTrack>]> {
Ref::map(self.tracks.borrow(), |tracks| &**tracks)
}

pub fn add_track(&self, track: &MediaStreamTrack) {
self.tracks.borrow_mut().push(Dom::from_ref(track))
}
}

impl MediaStreamMethods for MediaStream {
/// https://w3c.github.io/mediacapture-main/#dom-mediastream-gettracks
fn GetTracks(&self) -> Vec<DomRoot<MediaStreamTrack>> {
self.tracks
.borrow()
.iter()
.map(|x| DomRoot::from_ref(&**x))
.collect()
}

/// https://w3c.github.io/mediacapture-main/#dom-mediastream-getaudiotracks
fn GetAudioTracks(&self) -> Vec<DomRoot<MediaStreamTrack>> {
self.tracks
.borrow()
.iter()
.filter(|x| x.ty() == MediaStreamType::Audio)
.map(|x| DomRoot::from_ref(&**x))
.collect()
}

/// https://w3c.github.io/mediacapture-main/#dom-mediastream-getvideotracks
fn GetVideoTracks(&self) -> Vec<DomRoot<MediaStreamTrack>> {
self.tracks
.borrow()
.iter()
.filter(|x| x.ty() == MediaStreamType::Video)
.map(|x| DomRoot::from_ref(&**x))
.collect()
}

/// https://w3c.github.io/mediacapture-main/#dom-mediastream-gettrackbyid
fn GetTrackById(&self, id: DOMString) -> Option<DomRoot<MediaStreamTrack>> {
self.tracks
.borrow()
.iter()
.find(|x| x.id().id().to_string() == &*id)
.map(|x| DomRoot::from_ref(&**x))
}

/// https://w3c.github.io/mediacapture-main/#dom-mediastream-addtrack
fn AddTrack(&self, track: &MediaStreamTrack) {
let existing = self.tracks.borrow().iter().find(|x| *x == &track).is_some();

if existing {
return;
}
self.add_track(track)
}

/// https://w3c.github.io/mediacapture-main/#dom-mediastream-removetrack
fn RemoveTrack(&self, track: &MediaStreamTrack) {
self.tracks.borrow_mut().retain(|x| *x != track);
}

/// https://w3c.github.io/mediacapture-main/#dom-mediastream-clone
fn Clone(&self) -> DomRoot<MediaStream> {
let new = MediaStream::new(&self.global());
for track in &*self.tracks.borrow() {
new.add_track(&track)
}
new
}
}
@@ -0,0 +1,74 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use crate::dom::bindings::codegen::Bindings::MediaStreamTrackBinding::{
self, MediaStreamTrackMethods,
};
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
use crate::dom::eventtarget::EventTarget;
use crate::dom::globalscope::GlobalScope;
use dom_struct::dom_struct;
use servo_media::streams::registry::MediaStreamId;
use servo_media::streams::MediaStreamType;

#[dom_struct]
pub struct MediaStreamTrack {
eventtarget: EventTarget,
#[ignore_malloc_size_of = "defined in servo-media"]
id: MediaStreamId,
#[ignore_malloc_size_of = "defined in servo-media"]
ty: MediaStreamType,
}

impl MediaStreamTrack {
pub fn new_inherited(id: MediaStreamId, ty: MediaStreamType) -> MediaStreamTrack {
MediaStreamTrack {
eventtarget: EventTarget::new_inherited(),
id,
ty,
}
}

pub fn new(
global: &GlobalScope,
id: MediaStreamId,
ty: MediaStreamType,
) -> DomRoot<MediaStreamTrack> {
reflect_dom_object(
Box::new(MediaStreamTrack::new_inherited(id, ty)),
global,
MediaStreamTrackBinding::Wrap,
)
}

pub fn id(&self) -> MediaStreamId {
self.id
}

pub fn ty(&self) -> MediaStreamType {
self.ty
}
}

impl MediaStreamTrackMethods for MediaStreamTrack {
/// https://w3c.github.io/mediacapture-main/#dom-mediastreamtrack-kind
fn Kind(&self) -> DOMString {
match self.ty {
MediaStreamType::Video => "video".into(),
MediaStreamType::Audio => "audio".into(),
}
}

/// https://w3c.github.io/mediacapture-main/#dom-mediastreamtrack-id
fn Id(&self) -> DOMString {
self.id.id().to_string().into()
}

/// https://w3c.github.io/mediacapture-main/#dom-mediastreamtrack-clone
fn Clone(&self) -> DomRoot<MediaStreamTrack> {
MediaStreamTrack::new(&self.global(), self.id, self.ty)
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.