From 041794c1f38dcf68c6c71c5fb9b8dfd8cedccc5a Mon Sep 17 00:00:00 2001 From: Jim Mathies Date: Fri, 12 Sep 2014 09:49:39 -0500 Subject: [PATCH] Bug 1060738 - Switch to using chromium's Thread/tasks in MediaManager. On Windows, use MessagePumpForNonMainUIThreads for the background media thread. r=jesup --- content/base/src/nsDocument.cpp | 13 +- dom/media/MediaManager.cpp | 222 +++++++++++++++++++------------- dom/media/MediaManager.h | 58 ++++----- 3 files changed, 165 insertions(+), 128 deletions(-) diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 797639e13c6e..77edf9a85692 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -149,12 +149,6 @@ #include "nsHtml5TreeOpExecutor.h" #include "mozilla/dom/HTMLLinkElement.h" #include "mozilla/dom/HTMLMediaElement.h" -#ifdef MOZ_MEDIA_NAVIGATOR -#include "mozilla/MediaManager.h" -#endif // MOZ_MEDIA_NAVIGATOR -#ifdef MOZ_WEBRTC -#include "IPeerConnection.h" -#endif // MOZ_WEBRTC #include "mozAutoDocUpdate.h" #include "nsGlobalWindow.h" @@ -229,6 +223,13 @@ #include "nsWindowMemoryReporter.h" #include "nsLocation.h" +#ifdef MOZ_MEDIA_NAVIGATOR +#include "mozilla/MediaManager.h" +#endif // MOZ_MEDIA_NAVIGATOR +#ifdef MOZ_WEBRTC +#include "IPeerConnection.h" +#endif // MOZ_WEBRTC + using namespace mozilla; using namespace mozilla::dom; diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index 8b68d51ffef1..d0a35850fa29 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -851,15 +851,13 @@ public: // Dispatch to the media thread to ask it to start the sources, // because that can take a while. - // Pass ownership of trackunion to the MediaOperationRunnable - // to ensure it's kept alive until the MediaOperationRunnable runs (at least). - nsIThread *mediaThread = MediaManager::GetThread(); - nsRefPtr runnable( - new MediaOperationRunnable(MEDIA_START, mListener, trackunion, - tracksAvailableCallback, - mAudioSource, mVideoSource, false, mWindowID, - mError.forget())); - mediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL); + // Pass ownership of trackunion to the MediaOperationTask + // to ensure it's kept alive until the MediaOperationTask runs (at least). + MediaManager::GetMessageLoop()->PostTask(FROM_HERE, + new MediaOperationTask(MEDIA_START, mListener, trackunion, + tracksAvailableCallback, + mAudioSource, mVideoSource, false, mWindowID, + mError.forget())); // We won't need mError now. mError = nullptr; @@ -1050,10 +1048,10 @@ static SourceSet * * Do not run this on the main thread. The success and error callbacks *MUST* * be dispatched on the main thread! */ -class GetUserMediaRunnable : public nsRunnable +class GetUserMediaTask : public Task { public: - GetUserMediaRunnable( + GetUserMediaTask( const MediaStreamConstraints& aConstraints, already_AddRefed aSuccess, already_AddRefed aError, @@ -1074,7 +1072,7 @@ public: * The caller can also choose to provide their own backend instead of * using the one provided by MediaManager::GetBackend. */ - GetUserMediaRunnable( + GetUserMediaTask( const MediaStreamConstraints& aConstraints, already_AddRefed aSuccess, already_AddRefed aError, @@ -1092,7 +1090,7 @@ public: , mManager(MediaManager::GetInstance()) {} - ~GetUserMediaRunnable() { + ~GetUserMediaTask() { } void @@ -1106,7 +1104,7 @@ public: NS_DispatchToMainThread(runnable); } - NS_IMETHOD + void Run() { NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread"); @@ -1123,7 +1121,7 @@ public: if (!mDeviceChosen) { nsresult rv = SelectDevice(backend); if (rv != NS_OK) { - return rv; + return; } } @@ -1131,12 +1129,12 @@ public: if (mConstraints.mPicture && (IsOn(mConstraints.mAudio) || IsOn(mConstraints.mVideo))) { Fail(NS_LITERAL_STRING("NOT_SUPPORTED_ERR")); - return NS_OK; + return; } if (mConstraints.mPicture) { ProcessGetUserMediaSnapshot(mVideoDevice->GetSource(), 0); - return NS_OK; + return; } // There's a bug in the permission code that can leave us with mAudio but no audio device @@ -1144,7 +1142,6 @@ public: mAudioDevice->GetSource() : nullptr), ((IsOn(mConstraints.mVideo) && mVideoDevice) ? mVideoDevice->GetSource() : nullptr)); - return NS_OK; } nsresult @@ -1334,16 +1331,38 @@ private: nsRefPtr mManager; // get ref to this when creating the runnable }; +#if defined(ANDROID) && !defined(MOZ_WIDGET_GONK) +class GetUserMediaRunnableWrapper : public nsRunnable +{ +public: + // This object must take ownership of task + GetUserMediaRunnableWrapper(GetUserMediaTask* task) : + mTask(task) { + } + + ~GetUserMediaRunnableWrapper() { + } + + NS_IMETHOD Run() { + mTask->Run(); + return NS_OK; + } + +private: + nsAutoPtr mTask; +}; +#endif + /** - * Similar to GetUserMediaRunnable, but used for the chrome-only + * Similar to GetUserMediaTask, but used for the chrome-only * GetUserMediaDevices function. Enumerates a list of audio & video devices, * wraps them up in nsIMediaDevice objects and returns it to the success * callback. */ -class GetUserMediaDevicesRunnable : public nsRunnable +class GetUserMediaDevicesTask : public Task { public: - GetUserMediaDevicesRunnable( + GetUserMediaDevicesTask( const MediaStreamConstraints& aConstraints, already_AddRefed aSuccess, already_AddRefed aError, @@ -1357,7 +1376,7 @@ public: , mLoopbackAudioDevice(aAudioLoopbackDev) , mLoopbackVideoDevice(aVideoLoopbackDev) {} - NS_IMETHOD + void // NS_IMETHOD Run() { NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread"); @@ -1389,7 +1408,6 @@ public: final.forget())); // DeviceSuccessCallbackRunnable should have taken these. MOZ_ASSERT(!mSuccess && !mError); - return NS_OK; } private: @@ -1437,12 +1455,23 @@ NS_IMPL_ISUPPORTS(MediaManager, nsIMediaManagerService, nsIObserver) /* static */ MediaManager* MediaManager::Get() { if (!sSingleton) { + NS_ASSERTION(NS_IsMainThread(), "Only create MediaManager on main thread"); + sSingleton = new MediaManager(); - NS_NewNamedThread("MediaManager", getter_AddRefs(sSingleton->mMediaThread)); + sSingleton->mMediaThread = new base::Thread("MediaManager"); + base::Thread::Options options; +#if defined(_WIN32) + options.message_loop_type = MessageLoop::TYPE_MOZILLA_NONMAINUITHREAD; +#else + options.message_loop_type = MessageLoop::TYPE_MOZILLA_NONMAINTHREAD; +#endif + if (!sSingleton->mMediaThread->StartWithOptions(options)) { + MOZ_CRASH(); + } + LOG(("New Media thread for gum")); - NS_ASSERTION(NS_IsMainThread(), "Only create MediaManager on main thread"); nsCOMPtr obs = services::GetObserverService(); if (obs) { obs->AddObserver(sSingleton, "xpcom-shutdown", false); @@ -1471,6 +1500,15 @@ MediaManager::GetInstance() return service.forget(); } +/* static */ +MessageLoop* +MediaManager::GetMessageLoop() +{ + NS_ASSERTION(Get(), "MediaManager singleton?"); + NS_ASSERTION(Get()->mMediaThread, "No thread yet"); + return Get()->mMediaThread->message_loop(); +} + /* static */ nsresult MediaManager::NotifyRecordingStatusChange(nsPIDOMWindow* aWindow, const nsString& aMsg, @@ -1606,12 +1644,9 @@ MediaManager::GetUserMedia(bool aPrivileged, GetActiveWindows()->Put(windowID, listeners); } - // Ensure there's a thread for gum to proxy to off main thread - nsIThread *mediaThread = MediaManager::GetThread(); - // Create a disabled listener to act as a placeholder GetUserMediaCallbackMediaStreamListener* listener = - new GetUserMediaCallbackMediaStreamListener(mediaThread, windowID); + new GetUserMediaCallbackMediaStreamListener(mMediaThread, windowID); // No need for locking because we always do this in the main thread. listeners->AppendElement(listener); @@ -1663,15 +1698,15 @@ MediaManager::GetUserMedia(bool aPrivileged, } } - // Pass callbacks and MediaStreamListener along to GetUserMediaRunnable. - nsRefPtr runnable; + // Pass callbacks and MediaStreamListener along to GetUserMediaTask. + nsAutoPtr task; if (c.mFake) { // Fake stream from default backend. - runnable = new GetUserMediaRunnable(c, onSuccess.forget(), + task = new GetUserMediaTask(c, onSuccess.forget(), onError.forget(), windowID, listener, mPrefs, new MediaEngineDefault()); } else { // Stream from default device from WebRTC backend. - runnable = new GetUserMediaRunnable(c, onSuccess.forget(), + task = new GetUserMediaTask(c, onSuccess.forget(), onError.forget(), windowID, listener, mPrefs); } @@ -1683,10 +1718,10 @@ MediaManager::GetUserMedia(bool aPrivileged, if (tc.mMediaSource != dom::MediaSourceEnum::Camera) { if (tc.mMediaSource == dom::MediaSourceEnum::Browser) { if (!Preferences::GetBool("media.getusermedia.browser.enabled", false)) { - return runnable->Denied(NS_LITERAL_STRING("PERMISSION_DENIED")); + return task->Denied(NS_LITERAL_STRING("PERMISSION_DENIED")); } } else if (!Preferences::GetBool("media.getusermedia.screensharing.enabled", false)) { - return runnable->Denied(NS_LITERAL_STRING("PERMISSION_DENIED")); + return task->Denied(NS_LITERAL_STRING("PERMISSION_DENIED")); } /* Deny screensharing if the requesting document is not from a host on the whitelist. */ @@ -1704,7 +1739,7 @@ MediaManager::GetUserMedia(bool aPrivileged, ) || #endif (!aPrivileged && !HostHasPermission(*docURI))) { - return runnable->Denied(NS_LITERAL_STRING("PERMISSION_DENIED")); + return task->Denied(NS_LITERAL_STRING("PERMISSION_DENIED")); } } } @@ -1718,7 +1753,8 @@ MediaManager::GetUserMedia(bool aPrivileged, #if defined(ANDROID) && !defined(MOZ_WIDGET_GONK) if (c.mPicture) { // ShowFilePickerForMimeType() must run on the Main Thread! (on Android) - NS_DispatchToMainThread(runnable); + // Note, GetUserMediaRunnableWrapper takes ownership of task. + NS_DispatchToMainThread(new GetUserMediaRunnableWrapper(task.forget())); return NS_OK; } #endif @@ -1737,7 +1773,7 @@ MediaManager::GetUserMedia(bool aPrivileged, // XXX No full support for picture in Desktop yet (needs proper UI) if (aPrivileged || (c.mFake && !Preferences::GetBool("media.navigator.permission.fake"))) { - mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL); + MediaManager::GetMessageLoop()->PostTask(FROM_HERE, task.forget()); } else { bool isHTTPS = false; if (docURI) { @@ -1766,12 +1802,12 @@ MediaManager::GetUserMedia(bool aPrivileged, if ((!IsOn(c.mAudio) || audioPerm == nsIPermissionManager::DENY_ACTION) && (!IsOn(c.mVideo) || videoPerm == nsIPermissionManager::DENY_ACTION)) { - return runnable->Denied(NS_LITERAL_STRING("PERMISSION_DENIED")); + return task->Denied(NS_LITERAL_STRING("PERMISSION_DENIED")); } - // Ask for user permission, and dispatch runnable (or not) when a response + // Ask for user permission, and dispatch task (or not) when a response // is received via an observer notification. Each call is paired with its - // runnable by a GUID. + // task by a GUID. nsCOMPtr uuidgen = do_GetService("@mozilla.org/uuid-generator;1", &rv); NS_ENSURE_SUCCESS(rv, rv); @@ -1785,8 +1821,8 @@ MediaManager::GetUserMedia(bool aPrivileged, id.ToProvidedString(buffer); NS_ConvertUTF8toUTF16 callID(buffer); - // Store the current unarmed runnable w/callbacks. - mActiveCallbacks.Put(callID, runnable); + // Store the current unarmed task w/callbacks. + mActiveCallbacks.Put(callID, task.forget()); // Add a WindowID cross-reference so OnNavigation can tear things down nsTArray* array; @@ -1831,12 +1867,12 @@ MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow, nsAdoptingCString loopbackVideoDevice = Preferences::GetCString("media.video_loopback_dev"); - nsCOMPtr gUMDRunnable = new GetUserMediaDevicesRunnable( - aConstraints, onSuccess.forget(), onError.forget(), - (aInnerWindowID ? aInnerWindowID : aWindow->WindowID()), - loopbackAudioDevice, loopbackVideoDevice); + MediaManager::GetMessageLoop()->PostTask(FROM_HERE, + new GetUserMediaDevicesTask( + aConstraints, onSuccess.forget(), onError.forget(), + (aInnerWindowID ? aInnerWindowID : aWindow->WindowID()), + loopbackAudioDevice, loopbackVideoDevice)); - mMediaThread->Dispatch(gUMDRunnable, NS_DISPATCH_NORMAL); return NS_OK; } @@ -2018,8 +2054,7 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic, // Note: won't be released immediately as the Observer has a ref to us sSingleton = nullptr; if (mMediaThread) { - mMediaThread->Shutdown(); - mMediaThread = nullptr; + mMediaThread->Stop(); } mBackend = nullptr; } @@ -2028,11 +2063,11 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic, } else if (!strcmp(aTopic, "getUserMedia:response:allow")) { nsString key(aData); - nsRefPtr runnable; - if (!mActiveCallbacks.Get(key, getter_AddRefs(runnable))) { + nsAutoPtr task; + mActiveCallbacks.RemoveAndForget(key, task); + if (!task) { return NS_OK; } - mActiveCallbacks.Remove(key); if (aSubject) { // A particular device or devices were chosen by the user. @@ -2044,7 +2079,7 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic, MOZ_ASSERT(len); if (!len) { // neither audio nor video were selected - runnable->Denied(NS_LITERAL_STRING("PERMISSION_DENIED")); + task->Denied(NS_LITERAL_STRING("PERMISSION_DENIED")); return NS_OK; } for (uint32_t i = 0; i < len; i++) { @@ -2056,9 +2091,9 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic, nsString type; device->GetType(type); if (type.EqualsLiteral("video")) { - runnable->SetVideoDevice(static_cast(device.get())); + task->SetVideoDevice(static_cast(device.get())); } else if (type.EqualsLiteral("audio")) { - runnable->SetAudioDevice(static_cast(device.get())); + task->SetAudioDevice(static_cast(device.get())); } else { NS_WARNING("Unknown device type in getUserMedia"); } @@ -2067,7 +2102,7 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic, } // Reuse the same thread to save memory. - mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL); + MediaManager::GetMessageLoop()->PostTask(FROM_HERE, task.forget()); return NS_OK; } else if (!strcmp(aTopic, "getUserMedia:response:deny")) { @@ -2082,12 +2117,11 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic, } nsString key(aData); - nsRefPtr runnable; - if (!mActiveCallbacks.Get(key, getter_AddRefs(runnable))) { - return NS_OK; + nsAutoPtr task; + mActiveCallbacks.RemoveAndForget(key, task); + if (task) { + task->Denied(errorMessage); } - mActiveCallbacks.Remove(key); - runnable->Denied(errorMessage); return NS_OK; } else if (!strcmp(aTopic, "getUserMedia:revoke")) { @@ -2342,21 +2376,36 @@ MediaManager::StopMediaStreams() } } +void +GetUserMediaCallbackMediaStreamListener::AudioConfig(bool aEchoOn, + uint32_t aEcho, + bool aAgcOn, uint32_t aAGC, + bool aNoiseOn, uint32_t aNoise, + int32_t aPlayoutDelay) +{ + if (mAudioSource) { +#ifdef MOZ_WEBRTC + mMediaThread->message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(mAudioSource.get(), &MediaEngineSource::Config, + aEchoOn, aEcho, aAgcOn, aAGC, aNoiseOn, + aNoise, aPlayoutDelay)); +#endif + } +} + // Can be invoked from EITHER MainThread or MSG thread void GetUserMediaCallbackMediaStreamListener::Invalidate() { - - nsRefPtr runnable; // We can't take a chance on blocking here, so proxy this to another // thread. // Pass a ref to us (which is threadsafe) so it can query us for the // source stream info. - runnable = new MediaOperationRunnable(MEDIA_STOP, - this, nullptr, nullptr, - mAudioSource, mVideoSource, - mFinished, mWindowID, nullptr); - mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL); + MediaManager::GetMessageLoop()->PostTask(FROM_HERE, + new MediaOperationTask(MEDIA_STOP, + this, nullptr, nullptr, + mAudioSource, mVideoSource, + mFinished, mWindowID, nullptr)); } // Doesn't kill audio @@ -2370,12 +2419,11 @@ GetUserMediaCallbackMediaStreamListener::StopScreenWindowSharing() mVideoSource->GetMediaSource() == MediaSourceType::Application || mVideoSource->GetMediaSource() == MediaSourceType::Window)) { // Stop the whole stream if there's no audio; just the video track if we have both - nsRefPtr runnable( - new MediaOperationRunnable(mAudioSource ? MEDIA_STOP_TRACK : MEDIA_STOP, - this, nullptr, nullptr, - nullptr, mVideoSource, - mFinished, mWindowID, nullptr)); - mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL); + MediaManager::GetMessageLoop()->PostTask(FROM_HERE, + new MediaOperationTask(mAudioSource ? MEDIA_STOP_TRACK : MEDIA_STOP, + this, nullptr, nullptr, + nullptr, mVideoSource, + mFinished, mWindowID, nullptr)); } } @@ -2389,13 +2437,12 @@ GetUserMediaCallbackMediaStreamListener::StopTrack(TrackID aID, bool aIsAudio) { // XXX to support multiple tracks of a type in a stream, this should key off // the TrackID and not just the type - nsRefPtr runnable( - new MediaOperationRunnable(MEDIA_STOP_TRACK, - this, nullptr, nullptr, - aIsAudio ? mAudioSource : nullptr, - !aIsAudio ? mVideoSource : nullptr, - mFinished, mWindowID, nullptr)); - mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL); + MediaManager::GetMessageLoop()->PostTask(FROM_HERE, + new MediaOperationTask(MEDIA_STOP_TRACK, + this, nullptr, nullptr, + aIsAudio ? mAudioSource : nullptr, + !aIsAudio ? mVideoSource : nullptr, + mFinished, mWindowID, nullptr)); } else { LOG(("gUM track %d ended, but we don't have type %s", aID, aIsAudio ? "audio" : "video")); @@ -2416,12 +2463,11 @@ void GetUserMediaCallbackMediaStreamListener::NotifyDirectListeners(MediaStreamGraph* aGraph, bool aHasListeners) { - nsRefPtr runnable; - runnable = new MediaOperationRunnable(MEDIA_DIRECT_LISTENERS, - this, nullptr, nullptr, - mAudioSource, mVideoSource, - aHasListeners, mWindowID, nullptr); - mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL); + MediaManager::GetMessageLoop()->PostTask(FROM_HERE, + new MediaOperationTask(MEDIA_DIRECT_LISTENERS, + this, nullptr, nullptr, + mAudioSource, mVideoSource, + aHasListeners, mWindowID, nullptr)); } // Called from the MediaStreamGraph thread diff --git a/dom/media/MediaManager.h b/dom/media/MediaManager.h index f478a5fe4873..250c4cb53ea9 100644 --- a/dom/media/MediaManager.h +++ b/dom/media/MediaManager.h @@ -30,6 +30,10 @@ #include "mtransport/runnable_utils.h" #endif +// Note, these suck in Windows headers, unfortunately. +#include "base/thread.h" +#include "base/task.h" + #ifdef MOZ_WIDGET_GONK #include "DOMCameraManager.h" #endif @@ -57,7 +61,7 @@ class GetUserMediaCallbackMediaStreamListener : public MediaStreamListener { public: // Create in an inactive state - GetUserMediaCallbackMediaStreamListener(nsIThread *aThread, + GetUserMediaCallbackMediaStreamListener(base::Thread *aThread, uint64_t aWindowID) : mMediaThread(aThread) , mWindowID(aWindowID) @@ -144,7 +148,7 @@ public: mStopped = true; } - // implement in .cpp to avoid circular dependency with MediaOperationRunnable + // implement in .cpp to avoid circular dependency with MediaOperationTask // Can be invoked from EITHER MainThread or MSG thread void Invalidate(); @@ -152,19 +156,7 @@ public: AudioConfig(bool aEchoOn, uint32_t aEcho, bool aAgcOn, uint32_t aAGC, bool aNoiseOn, uint32_t aNoise, - int32_t aPlayoutDelay) - { - if (mAudioSource) { -#ifdef MOZ_WEBRTC - // Right now these configs are only of use if webrtc is available - RUN_ON_THREAD(mMediaThread, - WrapRunnable(nsRefPtr(mAudioSource), // threadsafe - &MediaEngineSource::Config, - aEchoOn, aEcho, aAgcOn, aAGC, aNoiseOn, aNoise, aPlayoutDelay), - NS_DISPATCH_NORMAL); -#endif - } - } + int32_t aPlayoutDelay); void Remove() @@ -230,7 +222,7 @@ public: private: // Set at construction - nsCOMPtr mMediaThread; + base::Thread* mMediaThread; uint64_t mWindowID; bool mStopped; // MainThread only @@ -299,7 +291,7 @@ typedef enum { } MediaOperation; class MediaManager; -class GetUserMediaRunnable; +class GetUserMediaTask; /** * Send an error back to content. The error is the form a string. @@ -340,11 +332,11 @@ private: // Generic class for running long media operations like Start off the main // thread, and then (because nsDOMMediaStreams aren't threadsafe), // ProxyReleases mStream since it's cycle collected. -class MediaOperationRunnable : public nsRunnable +class MediaOperationTask : public Task { public: // so we can send Stop without AddRef()ing from the MSG thread - MediaOperationRunnable(MediaOperation aType, + MediaOperationTask(MediaOperation aType, GetUserMediaCallbackMediaStreamListener* aListener, DOMMediaStream* aStream, DOMMediaStream::OnTracksAvailableCallback* aOnTracksAvailableCallback, @@ -364,12 +356,13 @@ public: , mError(aError) {} - ~MediaOperationRunnable() + ~MediaOperationTask() { // MediaStreams can be released on any thread. } - nsresult returnAndCallbackError(nsresult rv, const char* errorLog) + void + ReturnCallbackError(nsresult rv, const char* errorLog) { MM_LOG(("%s , rv=%d", errorLog, rv)); NS_DispatchToMainThread(new ReleaseMediaOperationResource(mStream.forget(), @@ -380,17 +373,16 @@ public: nsCOMPtr success; NS_DispatchToMainThread(new ErrorCallbackRunnable(success, mError, log, mWindowID)); - return NS_OK; } - NS_IMETHOD - Run() MOZ_OVERRIDE + void + Run() { SourceMediaStream *source = mListener->GetSourceStream(); // No locking between these is required as all the callbacks for the // same MediaStream will occur on the same thread. if (!source) // means the stream was never Activated() - return NS_OK; + return; switch (mType) { case MEDIA_START: @@ -406,7 +398,8 @@ public: if (NS_SUCCEEDED(rv)) { expectedTracks |= DOMMediaStream::HINT_CONTENTS_AUDIO; } else { - return returnAndCallbackError(rv, "Starting audio failed"); + ReturnCallbackError(rv, "Starting audio failed"); + return; } } if (mVideoSource) { @@ -414,7 +407,8 @@ public: if (NS_SUCCEEDED(rv)) { expectedTracks |= DOMMediaStream::HINT_CONTENTS_VIDEO; } else { - return returnAndCallbackError(rv, "Starting video failed"); + ReturnCallbackError(rv, "Starting video failed"); + return; } } @@ -481,7 +475,6 @@ public: MOZ_ASSERT(false,"invalid MediaManager operation"); break; } - return NS_OK; } private: @@ -545,16 +538,13 @@ public: // thread from the MainThread, as we NS_DISPATCH_SYNC to MainThread // from MediaManager thread. static MediaManager* Get(); + static MessageLoop* GetMessageLoop(); static bool Exists() { return !!sSingleton; } - static nsIThread* GetThread() { - return Get()->mMediaThread; - } - static nsresult NotifyRecordingStatusChange(nsPIDOMWindow* aWindow, const nsString& aMsg, const bool& aIsAudio, @@ -621,10 +611,10 @@ private: // ONLY access from MainThread so we don't need to lock WindowTable mActiveWindows; - nsRefPtrHashtable mActiveCallbacks; + nsClassHashtable mActiveCallbacks; nsClassHashtable> mCallIds; // Always exists - nsCOMPtr mMediaThread; + nsAutoPtr mMediaThread; Mutex mMutex; // protected with mMutex: