Bug 1208371 - Route ApplyConstraints through MediaStreamTrackSource. r=jib
MozReview-Commit-ID: CnJnxszKU4o
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1881,16 +1881,25 @@ public:
mElement->AddDecoderPrincipalChangeObserver(this);
}
MediaSourceEnum GetMediaSource() const override
{
return MediaSourceEnum::Other;
}
+ already_AddRefed<Promise>
+ ApplyConstraints(nsPIDOMWindowInner* aWindow,
+ const dom::MediaTrackConstraints& aConstraints,
+ ErrorResult &aRv) override
+ {
+ NS_ERROR("ApplyConstraints not implemented for media element capture");
+ return nullptr;
+ }
+
void Stop() override
{
NS_ERROR("We're reporting remote=true to not be stoppable. "
"Stop() should not be called.");
}
void NotifyDecoderPrincipalChanged() override
{
--- a/dom/media/AudioStreamTrack.h
+++ b/dom/media/AudioStreamTrack.h
@@ -18,16 +18,18 @@ public:
TrackID aInputTrackID, const nsString& aLabel,
MediaStreamTrackSource* aSource)
: MediaStreamTrack(aStream, aTrackID, aInputTrackID, aLabel, aSource) {}
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
AudioStreamTrack* AsAudioStreamTrack() override { return this; }
+ const AudioStreamTrack* AsAudioStreamTrack() const override { return this; }
+
// WebIDL
void GetKind(nsAString& aKind) override { aKind.AssignLiteral("audio"); }
};
} // namespace dom
} // namespace mozilla
#endif /* AUDIOSTREAMTRACK_H_ */
--- a/dom/media/DOMMediaStream.cpp
+++ b/dom/media/DOMMediaStream.cpp
@@ -13,18 +13,16 @@
#include "mozilla/dom/LocalMediaStreamBinding.h"
#include "mozilla/dom/AudioNode.h"
#include "AudioChannelAgent.h"
#include "mozilla/dom/AudioTrack.h"
#include "mozilla/dom/AudioTrackList.h"
#include "mozilla/dom/VideoTrack.h"
#include "mozilla/dom/VideoTrackList.h"
#include "mozilla/dom/HTMLCanvasElement.h"
-#include "mozilla/dom/MediaStreamError.h"
-#include "mozilla/dom/Promise.h"
#include "MediaStreamGraph.h"
#include "AudioStreamTrack.h"
#include "VideoStreamTrack.h"
#include "Layers.h"
// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
// GetTickCount() and conflicts with NS_DECL_NSIDOMMEDIASTREAM, containing
// currentTime getter.
@@ -745,35 +743,16 @@ DOMMediaStream::CreateAudioCaptureStream
{
// Audio capture doesn't create tracks dynamically
MediaStreamTrackSourceGetter* getter = nullptr;
RefPtr<DOMMediaStream> stream = new DOMMediaStream(aWindow, getter);
stream->InitAudioCaptureStream(aPrincipal, aGraph);
return stream.forget();
}
-already_AddRefed<Promise>
-DOMMediaStream::ApplyConstraintsToTrack(TrackID aTrackID,
- const MediaTrackConstraints& aConstraints,
- ErrorResult &aRv)
-{
- nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
- RefPtr<Promise> promise = Promise::Create(go, aRv);
- MOZ_RELEASE_ASSERT(!aRv.Failed());
-
- promise->MaybeReject(new MediaStreamError(
- mWindow,
- NS_LITERAL_STRING("OverconstrainedError"),
- NS_LITERAL_STRING(""),
- NS_LITERAL_STRING("")));
- return promise.forget();
-}
-
-
-
void
DOMMediaStream::PrincipalChanged(MediaStreamTrack* aTrack)
{
MOZ_ASSERT(aTrack);
NS_ASSERTION(HasTrack(*aTrack), "Principal changed for an unknown track");
LOG(LogLevel::Info, ("DOMMediaStream %p Principal changed for track %p",
this, aTrack));
RecomputePrincipal();
--- a/dom/media/DOMMediaStream.h
+++ b/dom/media/DOMMediaStream.h
@@ -416,21 +416,16 @@ public:
/**
* Overridden in DOMLocalMediaStreams to allow getUserMedia to pass
* data directly to RTCPeerConnection without going through graph queuing.
* Returns a bool to let us know if direct data will be delivered.
*/
virtual bool AddDirectListener(MediaStreamDirectListener *aListener) { return false; }
virtual void RemoveDirectListener(MediaStreamDirectListener *aListener) {}
- virtual already_AddRefed<dom::Promise>
- ApplyConstraintsToTrack(TrackID aTrackID,
- const MediaTrackConstraints& aConstraints,
- ErrorResult &aRv);
-
virtual DOMLocalMediaStream* AsDOMLocalMediaStream() { return nullptr; }
virtual DOMHwMediaStream* AsDOMHwMediaStream() { return nullptr; }
bool IsFinished();
/**
* Returns a principal indicating who may access this stream. The stream contents
* can only be accessed by principals subsuming this principal.
*/
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -687,61 +687,16 @@ public:
{
StopImpl();
if (GetSourceStream()) {
GetSourceStream()->Destroy();
}
}
- already_AddRefed<Promise>
- ApplyConstraintsToTrack(TrackID aTrackID,
- const MediaTrackConstraints& aConstraints,
- ErrorResult &aRv) override
- {
- nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
- RefPtr<Promise> promise = Promise::Create(go, aRv);
-
- if (sInShutdown) {
- RefPtr<MediaStreamError> error = new MediaStreamError(mWindow,
- NS_LITERAL_STRING("AbortError"),
- NS_LITERAL_STRING("In shutdown"));
- promise->MaybeReject(error);
- return promise.forget();
- }
- if (!GetSourceStream()) {
- RefPtr<MediaStreamError> error = new MediaStreamError(mWindow,
- NS_LITERAL_STRING("InternalError"),
- NS_LITERAL_STRING("No stream."));
- promise->MaybeReject(error);
- return promise.forget();
- }
-
- RefPtr<dom::MediaStreamTrack> track = FindOwnedDOMTrack(mOwnedStream, aTrackID);
- if (!track) {
- LOG(("ApplyConstraintsToTrack(%d) on non-existent track", aTrackID));
- RefPtr<MediaStreamError> error = new MediaStreamError(mWindow,
- NS_LITERAL_STRING("InternalError"),
- NS_LITERAL_STRING("No track."));
- promise->MaybeReject(error);
- return promise.forget();
- }
-
- typedef media::Pledge<bool, MediaStreamError*> PledgeVoid;
-
- RefPtr<PledgeVoid> p = mListener->ApplyConstraintsToTrack(mWindow,
- aTrackID, !!track->AsAudioStreamTrack(), aConstraints);
- p->Then([promise](bool& aDummy) mutable {
- promise->MaybeResolve(false);
- }, [promise](MediaStreamError*& reason) mutable {
- promise->MaybeReject(reason);
- });
- return promise.forget();
- }
-
// Allow getUserMedia to pass input data directly to PeerConnection/MediaPipeline
bool AddDirectListener(MediaStreamDirectListener *aListener) override
{
if (GetSourceStream()) {
GetSourceStream()->AddDirectListener(aListener);
return true; // application should ignore NotifyQueuedTrackData
}
return false;
@@ -920,16 +875,45 @@ public:
: MediaStreamTrackSource(aPrincipal, false), mListener(aListener),
mSource(aSource), mTrackID(aTrackID) {}
MediaSourceEnum GetMediaSource() const override
{
return mSource;
}
+ already_AddRefed<Promise>
+ ApplyConstraints(nsPIDOMWindowInner* aWindow,
+ const MediaTrackConstraints& aConstraints,
+ ErrorResult &aRv) override
+ {
+ nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(aWindow);
+ RefPtr<Promise> promise = Promise::Create(go, aRv);
+
+ if (sInShutdown) {
+ RefPtr<MediaStreamError> error = new MediaStreamError(aWindow,
+ NS_LITERAL_STRING("AbortError"),
+ NS_LITERAL_STRING("In shutdown"));
+ promise->MaybeReject(error);
+ return promise.forget();
+ }
+
+ typedef media::Pledge<bool, MediaStreamError*> PledgeVoid;
+
+ RefPtr<PledgeVoid> p =
+ mListener->ApplyConstraintsToTrack(aWindow, mTrackID, aConstraints);
+ p->Then([promise](bool& aDummy) mutable {
+ promise->MaybeResolve(false);
+ }, [promise](MediaStreamError*& reason) mutable {
+ promise->MaybeReject(reason);
+ });
+ return promise.forget();
+ }
+
+
void Stop() override
{
if (mListener) {
mListener->StopTrack(mTrackID);
mListener = nullptr;
}
}
@@ -3142,36 +3126,36 @@ GetUserMediaCallbackMediaStreamListener:
}
// ApplyConstraints for track
already_AddRefed<GetUserMediaCallbackMediaStreamListener::PledgeVoid>
GetUserMediaCallbackMediaStreamListener::ApplyConstraintsToTrack(
nsPIDOMWindowInner* aWindow,
TrackID aTrackID,
- bool aIsAudio,
const MediaTrackConstraints& aConstraints)
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<PledgeVoid> p = new PledgeVoid();
- if (!(((aIsAudio && mAudioDevice) ||
- (!aIsAudio && mVideoDevice)) && !mStopped))
+ // XXX to support multiple tracks of a type in a stream, this should key off
+ // the TrackID and not just the type
+ RefPtr<AudioDevice> audioDevice =
+ aTrackID == kAudioTrack ? mAudioDevice.get() : nullptr;
+ RefPtr<VideoDevice> videoDevice =
+ aTrackID == kVideoTrack ? mVideoDevice.get() : nullptr;
+
+ if (mStopped || (!audioDevice && !videoDevice))
{
LOG(("gUM track %d applyConstraints, but we don't have type %s",
- aTrackID, aIsAudio ? "audio" : "video"));
+ aTrackID, aTrackID == kAudioTrack ? "audio" : "video"));
p->Resolve(false);
return p.forget();
}
- // XXX to support multiple tracks of a type in a stream, this should key off
- // the TrackID and not just the type
- RefPtr<AudioDevice> audioDevice = aIsAudio ? mAudioDevice.get() : nullptr;
- RefPtr<VideoDevice> videoDevice = !aIsAudio ? mVideoDevice.get() : nullptr;
-
RefPtr<MediaManager> mgr = MediaManager::GetInstance();
uint32_t id = mgr->mOutstandingVoidPledges.Append(*p);
uint64_t windowId = aWindow->WindowID();
MediaManager::PostTask(FROM_HERE, NewTaskFrom([id, windowId,
audioDevice, videoDevice,
aConstraints]() mutable {
MOZ_ASSERT(MediaManager::IsInMediaThread());
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -170,17 +170,17 @@ public:
void StopSharing();
void StopTrack(TrackID aID);
typedef media::Pledge<bool, dom::MediaStreamError*> PledgeVoid;
already_AddRefed<PledgeVoid>
ApplyConstraintsToTrack(nsPIDOMWindowInner* aWindow,
- TrackID aID, bool aIsAudio,
+ TrackID aID,
const dom::MediaTrackConstraints& aConstraints);
// mVideo/AudioDevice are set by Activate(), so we assume they're capturing
// if set and represent a real capture device.
bool CapturingVideo()
{
MOZ_ASSERT(NS_IsMainThread());
return mVideoDevice && !mStopped &&
--- a/dom/media/MediaStreamTrack.cpp
+++ b/dom/media/MediaStreamTrack.cpp
@@ -22,16 +22,33 @@ namespace dom {
NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaStreamTrackSource)
NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaStreamTrackSource)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaStreamTrackSource)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION(MediaStreamTrackSource, mPrincipal)
+already_AddRefed<Promise>
+MediaStreamTrackSource::ApplyConstraints(nsPIDOMWindowInner* aWindow,
+ const dom::MediaTrackConstraints& aConstraints,
+ ErrorResult &aRv)
+{
+ nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(aWindow);
+ RefPtr<Promise> promise = Promise::Create(go, aRv);
+ MOZ_RELEASE_ASSERT(!aRv.Failed());
+
+ promise->MaybeReject(new MediaStreamError(
+ aWindow,
+ NS_LITERAL_STRING("OverconstrainedError"),
+ NS_LITERAL_STRING(""),
+ NS_LITERAL_STRING("")));
+ return promise.forget();
+}
+
MediaStreamTrack::MediaStreamTrack(DOMMediaStream* aStream, TrackID aTrackID,
TrackID aInputTrackID, const nsString& aLabel,
MediaStreamTrackSource* aSource)
: mOwningStream(aStream), mTrackID(aTrackID),
mInputTrackID(aInputTrackID), mSource(aSource), mLabel(aLabel),
mEnded(false), mEnabled(true), mRemote(aSource->IsRemote()), mStopped(false)
{
@@ -139,17 +156,18 @@ MediaStreamTrack::ApplyConstraints(const
if (MOZ_LOG_TEST(gMediaStreamTrackLog, LogLevel::Info)) {
nsString str;
aConstraints.ToJSON(str);
LOG(LogLevel::Info, ("MediaStreamTrack %p ApplyConstraints() with "
"constraints %s", this, NS_ConvertUTF16toUTF8(str).get()));
}
- return mOwningStream->ApplyConstraintsToTrack(mTrackID, aConstraints, aRv);
+ nsPIDOMWindowInner* window = mOwningStream->GetParentObject();
+ return GetSource().ApplyConstraints(window, aConstraints, aRv);
}
MediaStreamGraph*
MediaStreamTrack::Graph()
{
return GetOwnedStream()->Graph();
}
--- a/dom/media/MediaStreamTrack.h
+++ b/dom/media/MediaStreamTrack.h
@@ -75,16 +75,25 @@ public:
/**
* Forwards a photo request to backends that support it. Other backends return
* NS_ERROR_NOT_IMPLEMENTED to indicate that a MediaStreamGraph-based fallback
* should be used.
*/
virtual nsresult TakePhoto(MediaEnginePhotoCallback*) const { return NS_ERROR_NOT_IMPLEMENTED; }
/**
+ * We provide a fallback solution to ApplyConstraints() here.
+ * Sources that support ApplyConstraints() will have to override it.
+ */
+ virtual already_AddRefed<Promise>
+ ApplyConstraints(nsPIDOMWindowInner* aWindow,
+ const dom::MediaTrackConstraints& aConstraints,
+ ErrorResult &aRv);
+
+ /**
* Called by the source interface when all registered sinks have unregistered.
*/
virtual void Stop() = 0;
/**
* Called by each MediaStreamTrack clone on initialization.
*/
void RegisterSink(Sink* aSink)
@@ -189,16 +198,19 @@ public:
DOMEventTargetHelper)
nsPIDOMWindowInner* GetParentObject() const;
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override = 0;
virtual AudioStreamTrack* AsAudioStreamTrack() { return nullptr; }
virtual VideoStreamTrack* AsVideoStreamTrack() { return nullptr; }
+ virtual const AudioStreamTrack* AsAudioStreamTrack() const { return nullptr; }
+ virtual const VideoStreamTrack* AsVideoStreamTrack() const { return nullptr; }
+
// WebIDL
virtual void GetKind(nsAString& aKind) = 0;
void GetId(nsAString& aID) const;
void GetLabel(nsAString& aLabel) { aLabel.Assign(mLabel); }
bool Enabled() { return mEnabled; }
void SetEnabled(bool aEnabled);
void Stop();
already_AddRefed<Promise>
--- a/dom/media/VideoStreamTrack.h
+++ b/dom/media/VideoStreamTrack.h
@@ -18,16 +18,18 @@ public:
TrackID aInputTrackID, const nsString& aLabel,
MediaStreamTrackSource* aSource)
: MediaStreamTrack(aStream, aTrackID, aInputTrackID, aLabel, aSource) {}
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
VideoStreamTrack* AsVideoStreamTrack() override { return this; }
+ const VideoStreamTrack* AsVideoStreamTrack() const override { return this; }
+
// WebIDL
void GetKind(nsAString& aKind) override { aKind.AssignLiteral("video"); }
};
} // namespace dom
} // namespace mozilla
#endif /* VIDEOSTREAMTRACK_H_ */
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
@@ -153,16 +153,25 @@ public:
explicit RemoteTrackSource(nsIPrincipal* aPrincipal)
: dom::MediaStreamTrackSource(aPrincipal, true) {}
dom::MediaSourceEnum GetMediaSource() const override
{
return dom::MediaSourceEnum::Other;
}
+ already_AddRefed<dom::Promise>
+ ApplyConstraints(nsPIDOMWindowInner* aWindow,
+ const dom::MediaTrackConstraints& aConstraints,
+ ErrorResult &aRv) override
+ {
+ NS_ERROR("Can't ApplyConstraints() a remote source!");
+ return nullptr;
+ }
+
void Stop() override { NS_ERROR("Can't stop a remote source!"); }
void SetPrincipal(nsIPrincipal* aPrincipal)
{
mPrincipal = aPrincipal;
PrincipalChanged();
}