Bug 1255737 - Backout f31612f8f3bb (
Bug 1239873) from beta 48. r=jib, a=gchang
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -18,17 +18,16 @@
#include "mozilla/Attributes.h"
#include "TrackUnionStream.h"
#include "ImageContainer.h"
#include "AudioCaptureStream.h"
#include "AudioChannelService.h"
#include "AudioNodeStream.h"
#include "AudioNodeExternalInputStream.h"
#include "mozilla/dom/AudioContextBinding.h"
-#include "mozilla/media/MediaUtils.h"
#include <algorithm>
#include "DOMMediaStream.h"
#include "GeckoProfiler.h"
#include "mozilla/unused.h"
#include "mozilla/media/MediaUtils.h"
#ifdef MOZ_WEBRTC
#include "AudioOutputObserver.h"
#endif
@@ -1585,38 +1584,35 @@ MediaStreamGraphImpl::ApplyStreamUpdate(
stream->mWrapper->NotifyStreamFinished();
}
stream->NotifyMainThreadListeners();
}
}
void
-MediaStreamGraphImpl::ForceShutDown(ShutdownTicket* aShutdownTicket)
+MediaStreamGraphImpl::ForceShutDown()
{
NS_ASSERTION(NS_IsMainThread(), "Must be called on main thread");
STREAM_LOG(LogLevel::Debug, ("MediaStreamGraph %p ForceShutdown", this));
{
MonitorAutoLock lock(mMonitor);
mForceShutDown = true;
- mForceShutdownTicket = aShutdownTicket;
if (mLifecycleState == LIFECYCLE_THREAD_NOT_STARTED) {
// We *could* have just sent this a message to start up, so don't
// yank the rug out from under it. Tell it to startup and let it
// shut down.
RefPtr<GraphDriver> driver = CurrentDriver();
MonitorAutoUnlock unlock(mMonitor);
driver->Start();
}
EnsureNextIterationLocked();
}
}
-/* static */ StaticRefPtr<nsIAsyncShutdownBlocker> gMediaStreamGraphShutdownBlocker;
-
namespace {
class MediaStreamGraphShutDownRunnable : public nsRunnable {
public:
explicit MediaStreamGraphShutDownRunnable(MediaStreamGraphImpl* aGraph)
: mGraph(aGraph)
{}
NS_IMETHOD Run()
@@ -1635,23 +1631,16 @@ public:
if (mGraph->mDriver->AsAudioCallbackDriver()) {
MOZ_ASSERT(!mGraph->mDriver->AsAudioCallbackDriver()->InCallback());
}
#endif
mGraph->mDriver->Shutdown(); // This will wait until it's shutdown since
// we'll start tearing down the graph after this
- // We may be one of several graphs. Drop ticket to eventually unblock shutdown.
- mGraph->mForceShutdownTicket = nullptr;
-
- // We can't block past the final LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION
- // stage, since completion of that stage requires all streams to be freed,
- // which requires shutdown to proceed.
-
// mGraph's thread is not running so it's OK to do whatever here
if (mGraph->IsEmpty()) {
// mGraph is no longer needed, so delete it.
mGraph->Destroy();
} else {
// The graph is not empty. We must be in a forced shutdown, or a
// non-realtime graph that has finished processing. Some later
// AppendMessage will detect that the manager has been emptied, and
@@ -1708,16 +1697,24 @@ public:
{
// Make sure to run this message during shutdown too, to make sure
// that we balance the number of streams registered with the graph
// as they're destroyed during shutdown.
Run();
}
};
+class MediaStreamGraphShutdownObserver final : public nsIObserver
+{
+ ~MediaStreamGraphShutdownObserver() {}
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIOBSERVER
+};
+
} // namespace
void
MediaStreamGraphImpl::RunInStableState(bool aSourceIsMSG)
{
NS_ASSERTION(NS_IsMainThread(), "Must be called on main thread");
nsTArray<nsCOMPtr<nsIRunnable> > runnables;
@@ -3278,58 +3275,49 @@ MediaStreamGraphImpl::Destroy()
{
// First unregister from memory reporting.
UnregisterWeakMemoryReporter(this);
// Clear the self reference which will destroy this instance.
mSelfRef = nullptr;
}
+NS_IMPL_ISUPPORTS(MediaStreamGraphShutdownObserver, nsIObserver)
+
+static bool gShutdownObserverRegistered = false;
+
+NS_IMETHODIMP
+MediaStreamGraphShutdownObserver::Observe(nsISupports *aSubject,
+ const char *aTopic,
+ const char16_t *aData)
+{
+ if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
+ for (auto iter = gGraphs.Iter(); !iter.Done(); iter.Next()) {
+ MediaStreamGraphImpl* graph = iter.UserData();
+ graph->ForceShutDown();
+ }
+ nsContentUtils::UnregisterShutdownObserver(this);
+ gShutdownObserverRegistered = false;
+ }
+ return NS_OK;
+}
+
MediaStreamGraph*
MediaStreamGraph::GetInstance(MediaStreamGraph::GraphDriverType aGraphDriverRequested,
dom::AudioChannel aChannel)
{
NS_ASSERTION(NS_IsMainThread(), "Main thread only");
uint32_t channel = static_cast<uint32_t>(aChannel);
MediaStreamGraphImpl* graph = nullptr;
if (!gGraphs.Get(channel, &graph)) {
- if (!gMediaStreamGraphShutdownBlocker) {
-
- class Blocker : public media::ShutdownBlocker
- {
- public:
- Blocker()
- : media::ShutdownBlocker(NS_LITERAL_STRING(
- "MediaStreamGraph shutdown: blocking on msg thread")) {}
-
- NS_IMETHOD
- BlockShutdown(nsIAsyncShutdownClient* aProfileBeforeChange) override
- {
- // Distribute the global async shutdown blocker in a ticket. If there
- // are zero graphs then shutdown is unblocked when we go out of scope.
- RefPtr<MediaStreamGraphImpl::ShutdownTicket> ticket =
- new MediaStreamGraphImpl::ShutdownTicket(gMediaStreamGraphShutdownBlocker.get());
- gMediaStreamGraphShutdownBlocker = nullptr;
-
- for (auto iter = gGraphs.Iter(); !iter.Done(); iter.Next()) {
- iter.UserData()->ForceShutDown(ticket);
- }
- return NS_OK;
- }
- };
-
- gMediaStreamGraphShutdownBlocker = new Blocker();
- nsCOMPtr<nsIAsyncShutdownClient> barrier = MediaStreamGraphImpl::GetShutdownBarrier();
- nsresult rv = barrier->
- AddBlocker(gMediaStreamGraphShutdownBlocker,
- NS_LITERAL_STRING(__FILE__), __LINE__,
- NS_LITERAL_STRING("MediaStreamGraph shutdown"));
- MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
+ if (!gShutdownObserverRegistered) {
+ gShutdownObserverRegistered = true;
+ nsContentUtils::RegisterShutdownObserver(new MediaStreamGraphShutdownObserver());
}
CubebUtils::InitPreferredSampleRate();
graph = new MediaStreamGraphImpl(aGraphDriverRequested,
CubebUtils::PreferredSampleRate(),
aChannel);
@@ -3367,17 +3355,17 @@ MediaStreamGraph::DestroyNonRealtimeInst
MediaStreamGraphImpl* graph = static_cast<MediaStreamGraphImpl*>(aGraph);
if (graph->mForceShutDown)
return; // already done
if (!graph->mNonRealtimeProcessing) {
// Start the graph, but don't produce anything
graph->StartNonRealtimeProcessing(0);
}
- graph->ForceShutDown(nullptr);
+ graph->ForceShutDown();
}
NS_IMPL_ISUPPORTS(MediaStreamGraphImpl, nsIMemoryReporter)
struct ArrayClearer
{
explicit ArrayClearer(nsTArray<AudioNodeSizes>& aArray) : mArray(aArray) {}
~ArrayClearer() { mArray.Clear(); }
--- a/dom/media/MediaStreamGraphImpl.h
+++ b/dom/media/MediaStreamGraphImpl.h
@@ -10,17 +10,16 @@
#include "nsDataHashtable.h"
#include "mozilla/Monitor.h"
#include "mozilla/TimeStamp.h"
#include "nsIMemoryReporter.h"
#include "nsIThread.h"
#include "nsIRunnable.h"
-#include "nsIAsyncShutdown.h"
#include "Latency.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WeakPtr.h"
#include "GraphDriver.h"
#include "AudioMixer.h"
namespace mozilla {
@@ -139,57 +138,23 @@ public:
*/
void ApplyStreamUpdate(StreamUpdate* aUpdate);
/**
* Append a ControlMessage to the message queue. This queue is drained
* during RunInStableState; the messages will run on the graph thread.
*/
void AppendMessage(UniquePtr<ControlMessage> aMessage);
- // Shutdown helpers.
-
- static already_AddRefed<nsIAsyncShutdownClient>
- GetShutdownBarrier()
- {
- nsCOMPtr<nsIAsyncShutdownService> svc = services::GetAsyncShutdown();
- MOZ_RELEASE_ASSERT(svc);
-
- nsCOMPtr<nsIAsyncShutdownClient> barrier;
- nsresult rv = svc->GetProfileBeforeChange(getter_AddRefs(barrier));
- if (!barrier) {
- // We are probably in a content process.
- rv = svc->GetContentChildShutdown(getter_AddRefs(barrier));
- }
- MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
- MOZ_RELEASE_ASSERT(barrier);
- return barrier.forget();
- }
-
- class ShutdownTicket final
- {
- public:
- explicit ShutdownTicket(nsIAsyncShutdownBlocker* aBlocker) : mBlocker(aBlocker) {}
- NS_INLINE_DECL_REFCOUNTING(ShutdownTicket)
- private:
- ~ShutdownTicket()
- {
- nsCOMPtr<nsIAsyncShutdownClient> barrier = GetShutdownBarrier();
- barrier->RemoveBlocker(mBlocker);
- }
-
- nsCOMPtr<nsIAsyncShutdownBlocker> mBlocker;
- };
-
/**
* Make this MediaStreamGraph enter forced-shutdown state. This state
* will be noticed by the media graph thread, which will shut down all streams
* and other state controlled by the media graph thread.
* This is called during application shutdown.
*/
- void ForceShutDown(ShutdownTicket* aShutdownTicket);
+ void ForceShutDown();
/**
* Called before the thread runs.
*/
void Init();
// The following methods run on the graph thread (or possibly the main thread if
// mLifecycleState > LIFECYCLE_RUNNING)
void AssertOnGraphThreadOrNotRunning() const
@@ -746,22 +711,16 @@ public:
* The graph should stop processing at or after this time.
*/
GraphTime mEndTime;
/**
* True when we need to do a forced shutdown during application shutdown.
*/
bool mForceShutDown;
-
- /**
- * Drop this reference during shutdown to unblock shutdown.
- **/
- RefPtr<ShutdownTicket> mForceShutdownTicket;
-
/**
* True when we have posted an event to the main thread to run
* RunInStableState() and the event hasn't run yet.
*/
bool mPostedRunInStableStateEvent;
// Main thread only