Confirmed users
770
edits
(Created page with "=MediaStream=") |
|||
Line 1: | Line 1: | ||
=MediaStream= | ==MediaStream from getUserMedia== | ||
Call flow of getUserMedia: | |||
<source lang="cpp"> | |||
Navigator::MozGetUserMedia(const MediaStreamConstraints& aConstraints, | |||
NavigatorUserMediaSuccessCallback& aOnSuccess, | |||
NavigatorUserMediaErrorCallback& aOnError, | |||
ErrorResult& aRv) | |||
{ | |||
... | |||
MediaManager* manager = MediaManager::Get(); | |||
aRv = manager->GetUserMedia(privileged, mWindow, aConstraints, | |||
onsuccess, onerror); | |||
} | |||
nsresult | |||
MediaManager::GetUserMedia(bool aPrivileged, | |||
nsPIDOMWindow* aWindow, const MediaStreamConstraints& aConstraints, | |||
nsIDOMGetUserMediaSuccessCallback* aOnSuccess, | |||
nsIDOMGetUserMediaErrorCallback* aOnError) | |||
{ | |||
... | |||
StreamListeners* listeners = GetActiveWindows()->Get(windowID); | |||
if (!listeners) { | |||
listeners = new StreamListeners; | |||
GetActiveWindows()->Put(windowID, listeners); | |||
} | |||
... | |||
// Create a disabled listener to act as a placeholder | |||
GetUserMediaCallbackMediaStreamListener* listener = | |||
new GetUserMediaCallbackMediaStreamListener(mediaThread, windowID); | |||
// No need for locking because we always do this in the main thread. | |||
listeners->AppendElement(listener); | |||
... | |||
// Pass callbacks and MediaStreamListener along to GetUserMediaRunnable. | |||
nsRefPtr<GetUserMediaRunnable> runnable; | |||
if (c.mFake) { | |||
// Fake stream from default backend. | |||
runnable = new GetUserMediaRunnable(c, onSuccess.forget(), | |||
onError.forget(), windowID, listener, mPrefs, new MediaEngineDefault()); | |||
} else { | |||
// Stream from default device from WebRTC backend. | |||
runnable = new GetUserMediaRunnable(c, onSuccess.forget(), | |||
onError.forget(), windowID, listener, mPrefs); | |||
} | |||
... | |||
#ifdef MOZ_B2G_CAMERA | |||
if (mCameraManager == nullptr) { | |||
mCameraManager = nsDOMCameraManager::CreateInstance(aWindow); | |||
} | |||
#endif | |||
... | |||
if (aPrivileged || | |||
(c.mFake && !Preferences::GetBool("media.navigator.permission.fake"))) { | |||
mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL); | |||
} ... | |||
} | |||
NS_IMETHOD | |||
GetUserMediaRunnable::Run() | |||
{ | |||
MediaEngine* backend = mBackend; | |||
// Was a backend provided? | |||
if (!backend) { | |||
// backend will become MediaEngineWebRTC. | |||
backend = mManager->GetBackend(mWindowID); | |||
} | |||
// Was a device provided? | |||
if (!mDeviceChosen) { | |||
// SelectDevice will call void MediaEngineWebRTC::EnumerateVideoDevices(MediaSourceType aMediaSource, | |||
// nsTArray<nsRefPtr<MediaEngineVideoSource> >* aVSources). | |||
// It will new and append MediaEngineWebRTCVideoSource into aVSources. | |||
// Then pick the first devive. | |||
nsresult rv = SelectDevice(backend); | |||
if (rv != NS_OK) { | |||
return rv; | |||
} | |||
} | |||
... | |||
ProcessGetUserMedia(((IsOn(mConstraints.mAudio) && mAudioDevice) ? | |||
mAudioDevice->GetSource() : nullptr), | |||
((IsOn(mConstraints.mVideo) && mVideoDevice) ? | |||
mVideoDevice->GetSource() : nullptr)); | |||
return NS_OK; | |||
} | |||
void | |||
ProcessGetUserMedia(MediaEngineAudioSource* aAudioSource, | |||
MediaEngineVideoSource* aVideoSource) | |||
{ | |||
... | |||
if (aVideoSource) { | |||
rv = aVideoSource->Allocate(GetInvariant(mConstraints.mVideo), mPrefs); | |||
... | |||
} | |||
... | |||
NS_DispatchToMainThread(new GetUserMediaStreamRunnable( | |||
mSuccess, mError, mWindowID, mListener, aAudioSource, aVideoSource, | |||
peerIdentity | |||
)); | |||
... | |||
} | |||
NS_IMETHOD | |||
GetUserMediaStreamRunnable::Run() | |||
{ | |||
... | |||
// Create a media stream. | |||
nsRefPtr<nsDOMUserMediaStream> trackunion = | |||
nsDOMUserMediaStream::CreateTrackUnionStream(window, mAudioSource, | |||
mVideoSource); | |||
... | |||
MediaStreamGraph* gm = MediaStreamGraph::GetInstance(); | |||
nsRefPtr<SourceMediaStream> stream = gm->CreateSourceStream(nullptr); | |||
... | |||
trackunion->mSourceStream = stream; | |||
... | |||
// The listener was added at the beginning in an inactive state. | |||
// Activate our listener. We'll call Start() on the source when get a callback | |||
// that the MediaStream has started consuming. The listener is freed | |||
// when the page is invalidated (on navigation or close). | |||
mListener->Activate(stream.forget(), mAudioSource, mVideoSource); | |||
... | |||
// This will call to nsresult MediaEngineWebRTCVideoSource::Start(SourceMediaStream* aStream, TrackID aID) | |||
nsRefPtr<MediaOperationRunnable> runnable( | |||
new MediaOperationRunnable(MEDIA_START, mListener, trackunion, | |||
tracksAvailableCallback, | |||
mAudioSource, mVideoSource, false, mWindowID, | |||
mError.forget())); | |||
mediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL); | |||
// We won't need mError now. | |||
mError = nullptr; | |||
return NS_OK; | |||
} | |||
SourceMediaStream* | |||
MediaStreamGraph::CreateSourceStream(DOMMediaStream* aWrapper) | |||
{ | |||
SourceMediaStream* stream = new SourceMediaStream(aWrapper); | |||
NS_ADDREF(stream); | |||
MediaStreamGraphImpl* graph = static_cast<MediaStreamGraphImpl*>(this); | |||
stream->SetGraphImpl(graph); | |||
graph->AppendMessage(new CreateMessage(stream)); | |||
return stream; | |||
} | |||
virtual void CreateMessage::Run() MOZ_OVERRIDE | |||
{ | |||
mStream->GraphImpl()->AddStream(mStream); // It will call mStreams.AppendElement(aStream); | |||
mStream->Init(); | |||
} | |||
</source> |