Backed out 2 changesets (bug 1258143) for dom/media/tests/crashtests/791330.html failures CLOSED TREE

Backed out changeset 514420f15a67 (bug 1258143)
Backed out changeset 905c871bcf03 (bug 1258143)
This commit is contained in:
Bogdan Tara 2018-10-12 17:42:26 +03:00
Родитель cd546f12d8
Коммит db185e5d31
44 изменённых файлов: 470 добавлений и 57 удалений

Просмотреть файл

@ -507,6 +507,11 @@ DOMInterfaces = {
'wrapperCache': False, 'wrapperCache': False,
}, },
'LocalMediaStream': {
'headerFile': 'DOMMediaStream.h',
'nativeType': 'mozilla::DOMLocalMediaStream'
},
'MatchGlob': { 'MatchGlob': {
'nativeType': 'mozilla::extensions::MatchGlob', 'nativeType': 'mozilla::extensions::MatchGlob',
}, },

Просмотреть файл

@ -18,6 +18,7 @@
#include "mozilla/dom/AudioTrackList.h" #include "mozilla/dom/AudioTrackList.h"
#include "mozilla/dom/DocGroup.h" #include "mozilla/dom/DocGroup.h"
#include "mozilla/dom/HTMLCanvasElement.h" #include "mozilla/dom/HTMLCanvasElement.h"
#include "mozilla/dom/LocalMediaStreamBinding.h"
#include "mozilla/dom/MediaStreamBinding.h" #include "mozilla/dom/MediaStreamBinding.h"
#include "mozilla/dom/MediaStreamTrackEvent.h" #include "mozilla/dom/MediaStreamTrackEvent.h"
#include "mozilla/dom/Promise.h" #include "mozilla/dom/Promise.h"
@ -403,6 +404,13 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMMediaStream)
NS_INTERFACE_MAP_ENTRY(DOMMediaStream) NS_INTERFACE_MAP_ENTRY(DOMMediaStream)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
NS_IMPL_ADDREF_INHERITED(DOMLocalMediaStream, DOMMediaStream)
NS_IMPL_RELEASE_INHERITED(DOMLocalMediaStream, DOMMediaStream)
NS_INTERFACE_MAP_BEGIN(DOMLocalMediaStream)
NS_INTERFACE_MAP_ENTRY(DOMLocalMediaStream)
NS_INTERFACE_MAP_END_INHERITING(DOMMediaStream)
NS_IMPL_CYCLE_COLLECTION_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream, NS_IMPL_CYCLE_COLLECTION_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream,
mStreamNode) mStreamNode)
@ -1525,6 +1533,65 @@ DOMMediaStream::NotifyPlaybackTrackBlocked()
} }
} }
DOMLocalMediaStream::~DOMLocalMediaStream()
{
if (mInputStream) {
// Make sure Listeners of this stream know it's going away
StopImpl();
}
}
JSObject*
DOMLocalMediaStream::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return dom::LocalMediaStream_Binding::Wrap(aCx, this, aGivenProto);
}
void
DOMLocalMediaStream::Stop()
{
LOG(LogLevel::Debug, ("DOMMediaStream %p Stop()", this));
nsCOMPtr<nsPIDOMWindowInner> pWindow = GetParentObject();
nsIDocument* document = pWindow ? pWindow->GetExtantDoc() : nullptr;
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("Media"),
document,
nsContentUtils::eDOM_PROPERTIES,
"MediaStreamStopDeprecatedWarning");
StopImpl();
}
void
DOMLocalMediaStream::StopImpl()
{
if (mInputStream && mInputStream->AsSourceStream()) {
mInputStream->AsSourceStream()->EndAllTrackAndFinish();
}
}
already_AddRefed<DOMLocalMediaStream>
DOMLocalMediaStream::CreateSourceStreamAsInput(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter)
{
RefPtr<DOMLocalMediaStream> stream =
new DOMLocalMediaStream(aWindow, aTrackSourceGetter);
stream->InitSourceStream(aGraph);
return stream.forget();
}
already_AddRefed<DOMLocalMediaStream>
DOMLocalMediaStream::CreateTrackUnionStreamAsInput(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter)
{
RefPtr<DOMLocalMediaStream> stream =
new DOMLocalMediaStream(aWindow, aTrackSourceGetter);
stream->InitTrackUnionStream(aGraph);
return stream.forget();
}
DOMAudioNodeMediaStream::DOMAudioNodeMediaStream(nsPIDOMWindowInner* aWindow, AudioNode* aNode) DOMAudioNodeMediaStream::DOMAudioNodeMediaStream(nsPIDOMWindowInner* aWindow, AudioNode* aNode)
: DOMMediaStream(aWindow, nullptr), : DOMMediaStream(aWindow, nullptr),
mStreamNode(aNode) mStreamNode(aNode)

Просмотреть файл

@ -28,6 +28,7 @@
namespace mozilla { namespace mozilla {
class AbstractThread; class AbstractThread;
class DOMLocalMediaStream;
class DOMMediaStream; class DOMMediaStream;
class MediaStream; class MediaStream;
class MediaInputPort; class MediaInputPort;
@ -205,6 +206,7 @@ class DOMMediaStream : public DOMEventTargetHelper,
public dom::PrincipalChangeObserver<dom::MediaStreamTrack>, public dom::PrincipalChangeObserver<dom::MediaStreamTrack>,
public RelativeTimeline public RelativeTimeline
{ {
friend class DOMLocalMediaStream;
friend class dom::MediaStreamTrack; friend class dom::MediaStreamTrack;
typedef dom::MediaStreamTrack MediaStreamTrack; typedef dom::MediaStreamTrack MediaStreamTrack;
typedef dom::AudioStreamTrack AudioStreamTrack; typedef dom::AudioStreamTrack AudioStreamTrack;
@ -754,6 +756,49 @@ private:
NS_DEFINE_STATIC_IID_ACCESSOR(DOMMediaStream, NS_DEFINE_STATIC_IID_ACCESSOR(DOMMediaStream,
NS_DOMMEDIASTREAM_IID) NS_DOMMEDIASTREAM_IID)
#define NS_DOMLOCALMEDIASTREAM_IID \
{ 0xb1437260, 0xec61, 0x4dfa, \
{ 0x92, 0x54, 0x04, 0x44, 0xe2, 0xb5, 0x94, 0x9c } }
class DOMLocalMediaStream : public DOMMediaStream
{
public:
explicit DOMLocalMediaStream(nsPIDOMWindowInner* aWindow,
MediaStreamTrackSourceGetter* aTrackSourceGetter)
: DOMMediaStream(aWindow, aTrackSourceGetter) {}
NS_DECL_ISUPPORTS_INHERITED
NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOMLOCALMEDIASTREAM_IID)
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
void Stop();
/**
* Create an nsDOMLocalMediaStream whose underlying stream is a SourceMediaStream.
*/
static already_AddRefed<DOMLocalMediaStream>
CreateSourceStreamAsInput(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter = nullptr);
/**
* Create an nsDOMLocalMediaStream whose underlying stream is a TrackUnionStream.
*/
static already_AddRefed<DOMLocalMediaStream>
CreateTrackUnionStreamAsInput(nsPIDOMWindowInner* aWindow,
MediaStreamGraph* aGraph,
MediaStreamTrackSourceGetter* aTrackSourceGetter = nullptr);
protected:
virtual ~DOMLocalMediaStream();
void StopImpl();
};
NS_DEFINE_STATIC_IID_ACCESSOR(DOMLocalMediaStream,
NS_DOMLOCALMEDIASTREAM_IID)
class DOMAudioNodeMediaStream : public DOMMediaStream class DOMAudioNodeMediaStream : public DOMMediaStream
{ {
typedef dom::AudioNode AudioNode; typedef dom::AudioNode AudioNode;

Просмотреть файл

@ -1520,8 +1520,8 @@ public:
// fake tracks. Apart from them gUM never adds tracks dynamically. // fake tracks. Apart from them gUM never adds tracks dynamically.
domStream = new nsMainThreadPtrHolder<DOMMediaStream>( domStream = new nsMainThreadPtrHolder<DOMMediaStream>(
"GetUserMediaStreamRunnable::DOMMediaStreamMainThreadHolder", "GetUserMediaStreamRunnable::DOMMediaStreamMainThreadHolder",
DOMMediaStream::CreateSourceStreamAsInput(window, msg, DOMLocalMediaStream::CreateSourceStreamAsInput(window, msg,
new FakeTrackSourceGetter(principal))); new FakeTrackSourceGetter(principal)));
stream = domStream->GetInputStream()->AsSourceStream(); stream = domStream->GetInputStream()->AsSourceStream();
if (mAudioDevice) { if (mAudioDevice) {

Просмотреть файл

@ -825,8 +825,8 @@ public:
void RemoveAllDirectListenersImpl() override; void RemoveAllDirectListenersImpl() override;
/** /**
* End all tracks and Finish() this stream. Used to voluntarily revoke access * End all tracks and Finish() this stream. Used to voluntarily revoke access
* to a MediaStream. * to a LocalMediaStream.
*/ */
void EndAllTrackAndFinish(); void EndAllTrackAndFinish();

Просмотреть файл

@ -21,7 +21,7 @@ public:
, mIsWritingComplete(false) , mIsWritingComplete(false)
{} {}
virtual ~ContainerWriter() {} virtual ~ContainerWriter() {}
// Mapping to DOMMediaStream::TrackTypeHints // Mapping to DOMLocalMediaStream::TrackTypeHints
enum { enum {
CREATE_AUDIO_TRACK = 1 << 0, CREATE_AUDIO_TRACK = 1 << 0,
CREATE_VIDEO_TRACK = 1 << 1, CREATE_VIDEO_TRACK = 1 << 1,

Просмотреть файл

@ -27,7 +27,7 @@ interface nsIDOMGetUserMediaSuccessCallback : nsISupports
{ {
/* /*
* value must be a Blob if picture is true and a * value must be a Blob if picture is true and a
* DOMMediaStream if either audio or video are true. * DOMLocalMediaStream if either audio or video are true.
*/ */
void onSuccess(in nsISupports value); void onSuccess(in nsISupports value);
}; };

Просмотреть файл

@ -30,8 +30,8 @@ async function startTest() {
// no more requestData() to prevent busy main thread from starving // no more requestData() to prevent busy main thread from starving
// the encoding thread // the encoding thread
if (count == 30) { if (count == 30) {
info("track.stop"); info("stream.stop");
stream.getTracks()[0].stop(); stream.stop();
} else if (count < 30 && mediaRecorder.state == 'recording') { } else if (count < 30 && mediaRecorder.state == 'recording') {
info("requestData again"); info("requestData again");
mediaRecorder.requestData(); mediaRecorder.requestData();

Просмотреть файл

@ -131,7 +131,7 @@ async function startTest() {
checkTrackChanged(1, false); checkTrackChanged(1, false);
} else if (steps == 3) { } else if (steps == 3) {
checkTrackChanged(2, true); checkTrackChanged(2, true);
stream.getTracks().forEach(t => t.stop()); stream.stop();
} }
} }

Просмотреть файл

@ -105,7 +105,7 @@ async function startTest() {
element.onpause = onpause; element.onpause = onpause;
element.pause(); element.pause();
} else if (steps == 2) { } else if (steps == 2) {
stream.getTracks().forEach(t => t.stop()); stream.stop();
} }
} }

Просмотреть файл

@ -143,6 +143,76 @@ MediaStreamPlayback.prototype = {
} }
} }
/**
* This class is basically the same as MediaStreamPlayback except
* ensures that the instance provided startMedia is a MediaStream.
*
* @param {HTMLMediaElement} mediaElement the media element for playback
* @param {LocalMediaStream} mediaStream the media stream used in
* the mediaElement for playback
*/
function LocalMediaStreamPlayback(mediaElement, mediaStream) {
ok(mediaStream instanceof LocalMediaStream,
"Stream should be a LocalMediaStream");
MediaStreamPlayback.call(this, mediaElement, mediaStream);
}
LocalMediaStreamPlayback.prototype = Object.create(MediaStreamPlayback.prototype, {
/**
* DEPRECATED - MediaStream.stop() is going away. Use MediaStreamTrack.stop()!
*
* Starts media with a media stream, runs it until a canplaythrough and
* timeupdate event fires, and calls stop() on the stream.
*
* @param {Boolean} isResume specifies if this media element is being resumed
* from a previous run
*/
playMediaWithDeprecatedStreamStop : {
value: function(isResume) {
this.startMedia(isResume);
return this.verifyPlaying()
.then(() => this.deprecatedStopStreamInMediaPlayback())
.then(() => this.detachFromMediaElement());
}
},
/**
* DEPRECATED - MediaStream.stop() is going away. Use MediaStreamTrack.stop()!
*
* Stops the local media stream while it's currently in playback in
* a media element.
*
* Precondition: The media stream and element should both be actively
* being played.
*
*/
deprecatedStopStreamInMediaPlayback : {
value: function () {
return new Promise((resolve, reject) => {
/**
* Callback fired when the ended event fires when stop() is called on the
* stream.
*/
var endedCallback = () => {
this.mediaElement.removeEventListener('ended', endedCallback);
ok(true, "ended event successfully fired");
resolve();
};
this.mediaElement.addEventListener('ended', endedCallback);
this.mediaStream.stop();
// If ended doesn't fire in enough time, then we fail the test
setTimeout(() => {
reject(new Error("ended event never fired"));
}, ENDED_TIMEOUT_LENGTH);
});
}
}
});
// haxx to prevent SimpleTest from failing at window.onload // haxx to prevent SimpleTest from failing at window.onload
function addLoadEvent() {} function addLoadEvent() {}

Просмотреть файл

@ -99,6 +99,12 @@ skip-if = android_version == '18' # android(Bug 1189784, timeouts on 4.3 emulato
[test_getUserMedia_scarySources.html] [test_getUserMedia_scarySources.html]
skip-if = toolkit == 'android' # no screenshare or windowshare on android skip-if = toolkit == 'android' # no screenshare or windowshare on android
[test_getUserMedia_spinEventLoop.html] [test_getUserMedia_spinEventLoop.html]
[test_getUserMedia_stopAudioStream.html]
[test_getUserMedia_stopAudioStreamWithFollowupAudio.html]
[test_getUserMedia_stopVideoAudioStream.html]
[test_getUserMedia_stopVideoAudioStreamWithFollowupVideoAudio.html]
[test_getUserMedia_stopVideoStream.html]
[test_getUserMedia_stopVideoStreamWithFollowupVideo.html]
[test_getUserMedia_trackCloneCleanup.html] [test_getUserMedia_trackCloneCleanup.html]
[test_getUserMedia_trackEnded.html] [test_getUserMedia_trackEnded.html]
[test_getUserMedia_peerIdentity.html] [test_getUserMedia_peerIdentity.html]

Просмотреть файл

@ -27,7 +27,7 @@
checkMediaStreamContains(stream, [track, otherTrack], "Added video"); checkMediaStreamContains(stream, [track, otherTrack], "Added video");
var testElem = createMediaElement('video', 'testAddTrackAudioVideo'); var testElem = createMediaElement('video', 'testAddTrackAudioVideo');
var playback = new MediaStreamPlayback(testElem, stream); var playback = new LocalMediaStreamPlayback(testElem, stream);
return playback.playMedia(false); return playback.playMedia(false);
})) }))
.then(() => getUserMedia({video: true})).then(stream => .then(() => getUserMedia({video: true})).then(stream =>
@ -43,7 +43,7 @@
checkMediaStreamContains(stream, [track, otherTrack], "Added video"); checkMediaStreamContains(stream, [track, otherTrack], "Added video");
var test = createMediaElement('video', 'testAddTrackDoubleVideo'); var test = createMediaElement('video', 'testAddTrackDoubleVideo');
var playback = new MediaStreamPlayback(test, stream); var playback = new LocalMediaStreamPlayback(test, stream);
return playback.playMedia(false); return playback.playMedia(false);
})) }))
.then(() => getUserMedia({video: true})).then(stream => .then(() => getUserMedia({video: true})).then(stream =>
@ -80,7 +80,7 @@
.then(() => { .then(() => {
stream.addTrack(track); stream.addTrack(track);
checkMediaStreamContains(stream, [track], "Re-added added-then-removed track"); checkMediaStreamContains(stream, [track], "Re-added added-then-removed track");
var playback = new MediaStreamPlayback(elem, stream); var playback = new LocalMediaStreamPlayback(elem, stream);
return playback.playMedia(false); return playback.playMedia(false);
}) })
.then(() => otherTrack.stop()); .then(() => otherTrack.stop());
@ -98,7 +98,7 @@
"2, Added external track"); "2, Added external track");
var elem = createMediaElement('video', 'testAddRemoveOriginalTrackVideo'); var elem = createMediaElement('video', 'testAddRemoveOriginalTrackVideo');
var playback = new MediaStreamPlayback(elem, audioStream); var playback = new LocalMediaStreamPlayback(elem, audioStream);
return playback.playMedia(false); return playback.playMedia(false);
})) }))
.then(() => getUserMedia({ audio: true, video: true })).then(stream => { .then(() => getUserMedia({ audio: true, video: true })).then(stream => {

Просмотреть файл

@ -134,7 +134,7 @@ runTest(async function() {
for (let testCase of testCases) { for (let testCase of testCases) {
let testAudio = createMediaElement("audio", `testAudio.${testCase.id}`); let testAudio = createMediaElement("audio", `testAudio.${testCase.id}`);
let playback = new MediaStreamPlayback(testAudio, testCase.gumStream); let playback = new LocalMediaStreamPlayback(testAudio, testCase.gumStream);
await playback.playMediaWithoutStoppingTracks(false); await playback.playMediaWithoutStoppingTracks(false);
} }

Просмотреть файл

@ -107,7 +107,7 @@ runTest(async function() {
for (let testCase of testCases) { for (let testCase of testCases) {
let testAudio = createMediaElement("audio", `testAudio.${testCase.id}`); let testAudio = createMediaElement("audio", `testAudio.${testCase.id}`);
let playback = new MediaStreamPlayback(testAudio, testCase.gumStream); let playback = new LocalMediaStreamPlayback(testAudio, testCase.gumStream);
await playback.playMediaWithoutStoppingTracks(false); await playback.playMediaWithoutStoppingTracks(false);
} }

Просмотреть файл

@ -9,14 +9,14 @@
createHTML({ title: "getUserMedia Basic Audio Test", bug: "781534" }); createHTML({ title: "getUserMedia Basic Audio Test", bug: "781534" });
/** /**
* Run a test to verify that we can complete a start and stop media playback * Run a test to verify that we can complete a start and stop media playback
* cycle for an audio MediaStream on an audio HTMLMediaElement. * cycle for an audio LocalMediaStream on an audio HTMLMediaElement.
*/ */
runTest(function () { runTest(function () {
var testAudio = createMediaElement('audio', 'testAudio'); var testAudio = createMediaElement('audio', 'testAudio');
var constraints = {audio: true}; var constraints = {audio: true};
return getUserMedia(constraints).then(stream => { return getUserMedia(constraints).then(stream => {
var playback = new MediaStreamPlayback(testAudio, stream); var playback = new LocalMediaStreamPlayback(testAudio, stream);
return playback.playMedia(false); return playback.playMedia(false);
}); });
}); });

Просмотреть файл

@ -106,7 +106,7 @@
`Height setting ${settings.height} should be set after gUM (or 0 per bug 1453247)`); `Height setting ${settings.height} should be set after gUM (or 0 per bug 1453247)`);
draw(helper.red, helper.blue, draw(helper.red, helper.blue,
helper.green, helper.grey); helper.green, helper.grey);
let playback = new MediaStreamPlayback(testVideo, stream); let playback = new LocalMediaStreamPlayback(testVideo, stream);
playback.startMedia(); playback.startMedia();
await playback.verifyPlaying(); await playback.verifyPlaying();
settings = stream.getTracks()[0].getSettings(); settings = stream.getTracks()[0].getSettings();
@ -149,7 +149,7 @@
`Height setting ${settings.height} should be correct after gUM (or 0 per bug 1453247)`); `Height setting ${settings.height} should be correct after gUM (or 0 per bug 1453247)`);
draw(helper.green, helper.red, draw(helper.green, helper.red,
helper.grey, helper.blue); helper.grey, helper.blue);
playback = new MediaStreamPlayback(testVideo, stream); playback = new LocalMediaStreamPlayback(testVideo, stream);
playback.startMedia(); playback.startMedia();
await playback.verifyPlaying(); await playback.verifyPlaying();
settings = stream.getTracks()[0].getSettings(); settings = stream.getTracks()[0].getSettings();
@ -206,7 +206,7 @@
await verifyScreenshare(testVideo, helper, await verifyScreenshare(testVideo, helper,
helper.grey, helper.green, helper.grey, helper.green,
helper.blue, helper.red); helper.blue, helper.red);
await playback.stopTracksForStreamInMediaPlayback(); await playback.deprecatedStopStreamInMediaPlayback();
playback.detachFromMediaElement(); playback.detachFromMediaElement();
SpecialPowers.wrap(document).exitFullscreen(); SpecialPowers.wrap(document).exitFullscreen();

Просмотреть файл

@ -12,7 +12,7 @@
}); });
/** /**
* Run a test to verify that we can complete a start and stop media playback * Run a test to verify that we can complete a start and stop media playback
* cycle for a tabshare MediaStream on a video HTMLMediaElement. * cycle for a tabshare LocalMediaStream on a video HTMLMediaElement.
* *
* Additionally, exercise applyConstraints code for tabshare viewport offset. * Additionally, exercise applyConstraints code for tabshare viewport offset.
*/ */
@ -27,8 +27,8 @@
fake: false fake: false
})) }))
.then(stream => { .then(stream => {
var playback = new MediaStreamPlayback(testVideo, stream); var playback = new LocalMediaStreamPlayback(testVideo, stream);
return playback.playMedia(false); return playback.playMediaWithDeprecatedStreamStop(false);
}) })
.then(() => getUserMedia({ .then(() => getUserMedia({
video: { video: {
@ -41,7 +41,7 @@
fake: false fake: false
})) }))
.then(stream => { .then(stream => {
var playback = new MediaStreamPlayback(testVideo, stream); var playback = new LocalMediaStreamPlayback(testVideo, stream);
playback.startMedia(false); playback.startMedia(false);
return playback.verifyPlaying() return playback.verifyPlaying()
.then(() => Promise.all([ .then(() => Promise.all([
@ -55,7 +55,7 @@
() => listenUntil(testVideo, "resize", () => true) () => listenUntil(testVideo, "resize", () => true)
])) ]))
.then(() => playback.verifyPlaying()) // still playing .then(() => playback.verifyPlaying()) // still playing
.then(() => playback.stopTracksForStreamInMediaPlayback()) .then(() => playback.deprecatedStopStreamInMediaPlayback())
.then(() => playback.detachFromMediaElement()); .then(() => playback.detachFromMediaElement());
}); });
}); });

Просмотреть файл

@ -12,14 +12,14 @@
}); });
/** /**
* Run a test to verify that we can complete a start and stop media playback * Run a test to verify that we can complete a start and stop media playback
* cycle for an video MediaStream on a video HTMLMediaElement. * cycle for an video LocalMediaStream on a video HTMLMediaElement.
*/ */
runTest(function () { runTest(function () {
var testVideo = createMediaElement('video', 'testVideo'); var testVideo = createMediaElement('video', 'testVideo');
var constraints = {video: true}; var constraints = {video: true};
return getUserMedia(constraints).then(stream => { return getUserMedia(constraints).then(stream => {
var playback = new MediaStreamPlayback(testVideo, stream); var playback = new LocalMediaStreamPlayback(testVideo, stream);
return playback.playMedia(false); return playback.playMedia(false);
}); });
}); });

Просмотреть файл

@ -12,14 +12,14 @@
}); });
/** /**
* Run a test to verify that we can complete a start and stop media playback * Run a test to verify that we can complete a start and stop media playback
* cycle for a video and audio MediaStream on a video HTMLMediaElement. * cycle for a video and audio LocalMediaStream on a video HTMLMediaElement.
*/ */
runTest(function () { runTest(function () {
var testVideoAudio = createMediaElement('video', 'testVideoAudio'); var testVideoAudio = createMediaElement('video', 'testVideoAudio');
var constraints = {video: true, audio: true}; var constraints = {video: true, audio: true};
return getUserMedia(constraints).then(stream => { return getUserMedia(constraints).then(stream => {
var playback = new MediaStreamPlayback(testVideoAudio, stream); var playback = new LocalMediaStreamPlayback(testVideoAudio, stream);
return playback.playMedia(false); return playback.playMedia(false);
}); });
}); });

Просмотреть файл

@ -19,7 +19,7 @@
var constraints = {video: true}; var constraints = {video: true};
return getUserMedia(constraints).then(stream => { return getUserMedia(constraints).then(stream => {
var playback = new MediaStreamPlayback(testVideo, stream); var playback = new LocalMediaStreamPlayback(testVideo, stream);
var video = playback.mediaElement; var video = playback.mediaElement;
video.srcObject = stream; video.srcObject = stream;

Просмотреть файл

@ -12,7 +12,7 @@
}); });
/** /**
* Run a test to verify that we can complete a start and stop media playback * Run a test to verify that we can complete a start and stop media playback
* cycle for an screenshare MediaStream on a video HTMLMediaElement. * cycle for an screenshare LocalMediaStream on a video HTMLMediaElement.
*/ */
runTest(function () { runTest(function () {
var testVideo = createMediaElement('video', 'testVideo'); var testVideo = createMediaElement('video', 'testVideo');
@ -25,8 +25,8 @@
}; };
return getUserMedia(constraints).then(stream => { return getUserMedia(constraints).then(stream => {
var playback = new MediaStreamPlayback(testVideo, stream); var playback = new LocalMediaStreamPlayback(testVideo, stream);
return playback.playMedia(false); return playback.playMediaWithDeprecatedStreamStop(false);
}); });
}); });

Просмотреть файл

@ -22,7 +22,7 @@
navigator.mozGetUserMedia(constraints, stream => { navigator.mozGetUserMedia(constraints, stream => {
checkMediaStreamTracks(constraints, stream); checkMediaStreamTracks(constraints, stream);
var playback = new MediaStreamPlayback(testAudio, stream); var playback = new LocalMediaStreamPlayback(testAudio, stream);
return playback.playMedia(false) return playback.playMedia(false)
.then(() => resolve(), generateErrorCallback()); .then(() => resolve(), generateErrorCallback());
}, generateErrorCallback()) }, generateErrorCallback())

Просмотреть файл

@ -32,7 +32,7 @@
return; return;
} }
ok(stream, "getUserMedia should get a stream!"); ok(stream, "getUserMedia should get a stream!");
let playback = new MediaStreamPlayback(testAudio, stream); let playback = new LocalMediaStreamPlayback(testAudio, stream);
return playback.playMedia(false); return playback.playMedia(false);
}); });

Просмотреть файл

@ -16,19 +16,20 @@
return getUserMedia({video: true}) return getUserMedia({video: true})
.then(videoStream => { .then(videoStream => {
var testVideo = createMediaElement('video', 'testVideo'); var testVideo = createMediaElement('video', 'testVideo');
var videoPlayback = new MediaStreamPlayback(testVideo, var videoPlayback = new LocalMediaStreamPlayback(testVideo,
videoStream); videoStream);
return videoPlayback.playMediaWithoutStoppingTracks(false) return videoPlayback.playMedia(false)
.then(() => getUserMedia({audio: true})) .then(() => getUserMedia({audio: true}))
.then(audioStream => { .then(audioStream => {
var testAudio = createMediaElement('audio', 'testAudio'); var testAudio = createMediaElement('audio', 'testAudio');
var audioPlayback = new MediaStreamPlayback(testAudio, var audioPlayback = new LocalMediaStreamPlayback(testAudio,
audioStream); audioStream);
return audioPlayback.playMedia(false); return audioPlayback.playMedia(false)
.then(() => audioStream.stop());
}) })
.then(() => videoStream.getTracks().forEach(t => t.stop())); .then(() => videoStream.stop());
}); });
}); });

Просмотреть файл

@ -157,6 +157,8 @@ runTest(() => getUserMedia({audio: true, video: true})
"video element should capture only 1 video track until ended"); "video element should capture only 1 video track until ended");
untilEndedElement.srcObject.getTracks().forEach(t => t.stop()); untilEndedElement.srcObject.getTracks().forEach(t => t.stop());
// TODO(1208316) We stop the stream to make the media element end.
untilEndedElement.srcObject.stop();
return Promise.all([ return Promise.all([
haveEvent(untilEndedElement, "ended", wait(50000, new Error("Timeout"))), haveEvent(untilEndedElement, "ended", wait(50000, new Error("Timeout"))),

Просмотреть файл

@ -69,6 +69,7 @@ runTest(async () => {
// Not part of streamClone. Does not get stopped by the playback test. // Not part of streamClone. Does not get stopped by the playback test.
otherTrack.stop(); otherTrack.stop();
otherStream.stop();
let test = createMediaElement('video', 'testClonePlayback'); let test = createMediaElement('video', 'testClonePlayback');
let playback = new MediaStreamPlayback(test, streamClone); let playback = new MediaStreamPlayback(test, streamClone);

Просмотреть файл

@ -13,7 +13,7 @@
runTest(function () { runTest(function () {
return getUserMedia({audio: true}).then(audioStream => { return getUserMedia({audio: true}).then(audioStream => {
var testAudio = createMediaElement('audio', 'testAudio'); var testAudio = createMediaElement('audio', 'testAudio');
var playback = new MediaStreamPlayback(testAudio, audioStream); var playback = new LocalMediaStreamPlayback(testAudio, audioStream);
return playback.playMediaWithoutStoppingTracks(false) return playback.playMediaWithoutStoppingTracks(false)
.then(() => playback.playMedia(true)); .then(() => playback.playMedia(true));

Просмотреть файл

@ -13,7 +13,7 @@
runTest(function () { runTest(function () {
return getUserMedia({video: true, audio: true}).then(stream => { return getUserMedia({video: true, audio: true}).then(stream => {
var testVideo = createMediaElement('video', 'testVideo'); var testVideo = createMediaElement('video', 'testVideo');
var playback = new MediaStreamPlayback(testVideo, stream); var playback = new LocalMediaStreamPlayback(testVideo, stream);
return playback.playMediaWithoutStoppingTracks(false) return playback.playMediaWithoutStoppingTracks(false)
.then(() => playback.playMedia(true)); .then(() => playback.playMedia(true));

Просмотреть файл

@ -13,7 +13,7 @@
runTest(function () { runTest(function () {
return getUserMedia({video: true}).then(stream => { return getUserMedia({video: true}).then(stream => {
var testVideo = createMediaElement('video', 'testVideo'); var testVideo = createMediaElement('video', 'testVideo');
var streamPlayback = new MediaStreamPlayback(testVideo, stream); var streamPlayback = new LocalMediaStreamPlayback(testVideo, stream);
return streamPlayback.playMediaWithoutStoppingTracks(false) return streamPlayback.playMediaWithoutStoppingTracks(false)
.then(() => streamPlayback.playMedia(true)); .then(() => streamPlayback.playMedia(true));

Просмотреть файл

@ -0,0 +1,27 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({ title: "getUserMedia Stop Audio Stream", bug: "822109" });
/**
* Run a test to verify that we can start an audio stream in a media element,
* call stop() on the stream, and successfully get an ended event fired.
*/
runTest(function () {
return getUserMedia({audio: true})
.then(stream => {
var testAudio = createMediaElement('audio', 'testAudio');
var streamPlayback = new LocalMediaStreamPlayback(testAudio, stream);
return streamPlayback.playMediaWithDeprecatedStreamStop(false);
});
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,35 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({ title: "getUserMedia Stop Audio Stream With Followup Audio", bug: "822109" });
/**
* Run a test to verify that I can complete an audio gum playback in a media
* element, stop the stream, and then complete another audio gum playback
* in a media element.
*/
runTest(function () {
return getUserMedia({audio: true})
.then(firstStream => {
var testAudio = createMediaElement('audio', 'testAudio');
var streamPlayback = new LocalMediaStreamPlayback(testAudio, firstStream);
return streamPlayback.playMediaWithDeprecatedStreamStop(false)
.then(() => getUserMedia({audio: true}))
.then(secondStream => {
streamPlayback.mediaStream = secondStream;
return streamPlayback.playMedia(false)
.then(() => secondStream.stop());
});
});
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,28 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({ title: "getUserMedia Stop Video Audio Stream", bug: "822109" });
/**
* Run a test to verify that we can start a video+audio stream in a
* media element, call stop() on the stream, and successfully get an
* ended event fired.
*/
runTest(function () {
return getUserMedia({video: true, audio: true})
.then(stream => {
var testVideo = createMediaElement('video', 'testVideo');
var playback = new LocalMediaStreamPlayback(testVideo, stream);
return playback.playMediaWithDeprecatedStreamStop(false);
});
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,38 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
title: "getUserMedia Stop Video+Audio Stream With Followup Video+Audio",
bug: "822109"
});
/**
* Run a test to verify that I can complete an video+audio gum playback in a
* media element, stop the stream, and then complete another video+audio gum
* playback in a media element.
*/
runTest(function () {
return getUserMedia({video: true, audio: true})
.then(stream => {
var testVideo = createMediaElement('video', 'testVideo');
var streamPlayback = new LocalMediaStreamPlayback(testVideo, stream);
return streamPlayback.playMediaWithDeprecatedStreamStop(false)
.then(() => getUserMedia({video: true, audio: true}))
.then(secondStream => {
streamPlayback.mediaStream = secondStream;
return streamPlayback.playMedia(false)
.then(() => secondStream.stop());
});
});
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,28 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="mediaStreamPlayback.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({ title: "getUserMedia Stop Video Stream", bug: "822109" });
/**
* Run a test to verify that we can start a video stream in a
* media element, call stop() on the stream, and successfully get an
* ended event fired.
*/
runTest(function () {
return getUserMedia({video: true})
.then(stream => {
var testVideo = createMediaElement('video', 'testVideo');
var streamPlayback = new LocalMediaStreamPlayback(testVideo, stream);
return streamPlayback.playMediaWithDeprecatedStreamStop(false);
});
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,35 @@
<!DOCTYPE HTML>
<html>
<head>
<script src="mediaStreamPlayback.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({ title: "getUserMedia Stop Video Stream With Followup Video", bug: "822109" });
/**
* Run a test to verify that I can complete an video gum playback in a
* media element, stop the stream, and then complete another video gum
* playback in a media element.
*/
runTest(function () {
return getUserMedia({video: true})
.then(stream => {
var testVideo = createMediaElement('video', 'testVideo');
var streamPlayback = new LocalMediaStreamPlayback(testVideo, stream);
return streamPlayback.playMediaWithDeprecatedStreamStop(false)
.then(() => getUserMedia({video: true}))
.then(secondStream => {
streamPlayback.mediaStream = secondStream;
return streamPlayback.playMedia(false)
.then(() => secondStream.stop());
});
});
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -606,6 +606,8 @@ var interfaceNamesInGlobalScope =
{name: "KeyboardEvent", insecureContext: true}, {name: "KeyboardEvent", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
{name: "KeyframeEffect", insecureContext: true}, {name: "KeyframeEffect", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "LocalMediaStream", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!
{name: "Location", insecureContext: true}, {name: "Location", insecureContext: true},
// IMPORTANT: Do not change this list without review from a DOM peer! // IMPORTANT: Do not change this list without review from a DOM peer!

Просмотреть файл

@ -0,0 +1,15 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 http://mozilla.org/MPL/2.0/.
*
* The origins of this IDL file are
* http://dev.w3.org/2011/webrtc/editor/getusermedia.html
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
interface LocalMediaStream : MediaStream {
void stop();
};

Просмотреть файл

@ -172,6 +172,9 @@ with Files("KeyIdsInitData.webidl"):
with Files("Keyframe*"): with Files("Keyframe*"):
BUG_COMPONENT = ("Core", "DOM: Animation") BUG_COMPONENT = ("Core", "DOM: Animation")
with Files("LocalMediaStream.webidl"):
BUG_COMPONENT = ("Core", "Audio/Video")
with Files("MediaDevice*"): with Files("MediaDevice*"):
BUG_COMPONENT = ("Core", "WebRTC") BUG_COMPONENT = ("Core", "WebRTC")
@ -635,6 +638,7 @@ WEBIDL_FILES = [
'L10nUtils.webidl', 'L10nUtils.webidl',
'LegacyQueryInterface.webidl', 'LegacyQueryInterface.webidl',
'LinkStyle.webidl', 'LinkStyle.webidl',
'LocalMediaStream.webidl',
'Location.webidl', 'Location.webidl',
'MediaCapabilities.webidl', 'MediaCapabilities.webidl',
'MediaDeviceInfo.webidl', 'MediaDeviceInfo.webidl',

Просмотреть файл

@ -492,6 +492,8 @@ public:
return ds.forget(); return ds.forget();
} }
virtual void Stop() {} // Really DOMLocalMediaStream
virtual bool AddDirectListener(Fake_MediaStreamListener *aListener) { return false; } virtual bool AddDirectListener(Fake_MediaStreamListener *aListener) { return false; }
virtual void RemoveDirectListener(Fake_MediaStreamListener *aListener) {} virtual void RemoveDirectListener(Fake_MediaStreamListener *aListener) {}
@ -643,6 +645,7 @@ typedef Fake_MediaStreamListener MediaStreamListener;
typedef Fake_MediaStreamTrackListener MediaStreamTrackListener; typedef Fake_MediaStreamTrackListener MediaStreamTrackListener;
typedef Fake_DirectMediaStreamTrackListener DirectMediaStreamTrackListener; typedef Fake_DirectMediaStreamTrackListener DirectMediaStreamTrackListener;
typedef Fake_DOMMediaStream DOMMediaStream; typedef Fake_DOMMediaStream DOMMediaStream;
typedef Fake_DOMMediaStream DOMLocalMediaStream;
typedef Fake_MediaStreamVideoSink MediaStreamVideoSink; typedef Fake_MediaStreamVideoSink MediaStreamVideoSink;
namespace dom { namespace dom {

Просмотреть файл

@ -35,14 +35,14 @@
function stopMedia() { function stopMedia() {
if (video_status) { if (video_status) {
video.srcObject.getTracks().forEach(t => t.stop()); video.srcObject.stop();
video.srcObject = null; video.srcObject = null;
content.removeChild(video); content.removeChild(video);
capturing = false; capturing = false;
video_status = false; video_status = false;
} }
if (audio_status) { if (audio_status) {
audio.srcObject.getTracks().forEach(t => t.stop()); audio.srcObject.stop();
audio.srcObject = null; audio.srcObject = null;
content.removeChild(audio); content.removeChild(audio);
audio_status = false; audio_status = false;
@ -72,8 +72,8 @@
document.title += "video"; document.title += "video";
} }
document.title += " gumtest"; document.title += " gumtest";
audio.srcObject.getTracks().forEach(t => t.stop()); audio.srcObject.stop();
video.srcObject.getTracks().forEach(t => t.stop()); video.srcObject.stop();
}, function(err) { }, function(err) {
document.title = "failed gumtest"; document.title = "failed gumtest";
stopMedia(); stopMedia();

Просмотреть файл

@ -32,14 +32,14 @@
function stopMedia() { function stopMedia() {
if (video_status) { if (video_status) {
video.srcObject.getTracks().forEach(t => t.stop()); video.srcObject.stop();
video.srcObject = null; video.srcObject = null;
content.removeChild(video); content.removeChild(video);
capturing = false; capturing = false;
video_status = false; video_status = false;
} }
if (audio_status) { if (audio_status) {
audio.srcObject.getTracks().forEach(t => t.stop()); audio.srcObject.stop();
audio.srcObject = null; audio.srcObject = null;
content.removeChild(audio); content.removeChild(audio);
audio_status = false; audio_status = false;
@ -69,8 +69,8 @@
document.title += "video"; document.title += "video";
} }
document.title += " gumtest"; document.title += " gumtest";
audio.srcObject.getTracks().forEach(t => t.stop()); audio.srcObject.stop();
video.srcObject.getTracks().forEach(t => t.stop()); video.srcObject.stop();
}, function(err) { }, function(err) {
document.title = "failed gumtest"; document.title = "failed gumtest";
stopMedia(); stopMedia();

Просмотреть файл

@ -194,6 +194,7 @@ idl_test(
DragEvent: [], DragEvent: [],
NavigatorUserMediaError: [], NavigatorUserMediaError: [],
MediaStream: [], MediaStream: [],
LocalMediaStream: [],
MediaStreamTrack: [], MediaStreamTrack: [],
MediaStreamRecorder: [], MediaStreamRecorder: [],
PeerConnection: [], PeerConnection: [],

Просмотреть файл

@ -34,9 +34,9 @@ promise_test(async () => {
} }
} catch (e) {} } catch (e) {}
let stream, track, trackEvent; let track, trackEvent;
try { try {
stream = await navigator.mediaDevices.getUserMedia({audio: true}); const stream = await navigator.mediaDevices.getUserMedia({audio: true});
track = stream.getTracks()[0]; track = stream.getTracks()[0];
trackEvent = new MediaStreamTrackEvent("type", { trackEvent = new MediaStreamTrackEvent("type", {
track: track, track: track,
@ -49,7 +49,7 @@ promise_test(async () => {
idl_array.add_objects({ MediaDeviceInfo: [media] }); idl_array.add_objects({ MediaDeviceInfo: [media] });
} }
idl_array.add_objects({ idl_array.add_objects({
MediaStream: [stream, 'new MediaStream()'], MediaStream: ['new MediaStream()'],
Navigator: ['navigator'], Navigator: ['navigator'],
MediaDevices: ['navigator.mediaDevices'], MediaDevices: ['navigator.mediaDevices'],
MediaStreamTrack: [track], MediaStreamTrack: [track],