Bug 1250934: Split WebRTC MediaEngine shutdown into two stages to allow async shutdown r?padenot
MozReview-Commit-ID: 7LeFAbaTHMY
--- a/dom/media/webrtc/MediaEngine.h
+++ b/dom/media/webrtc/MediaEngine.h
@@ -84,16 +84,17 @@ public:
// code inside webrtc.org assumes these sizes; don't use anything smaller
// without verifying it's ok
static const unsigned int kMaxDeviceNameLength = 128;
static const unsigned int kMaxUniqueIdLength = 256;
virtual ~MediaEngineSource() {}
virtual void Shutdown() = 0;
+ virtual void ReleaseInterfaces() = 0;
/* Populate the human readable name of this device in the nsAString */
virtual void GetName(nsAString&) = 0;
/* Populate the UUID of this device in the nsACString */
virtual void GetUUID(nsACString&) = 0;
/* Release the device back to the system. */
--- a/dom/media/webrtc/MediaEngineDefault.h
+++ b/dom/media/webrtc/MediaEngineDefault.h
@@ -34,16 +34,17 @@ class MediaEngineDefault;
class MediaEngineDefaultVideoSource : public nsITimerCallback,
public MediaEngineVideoSource,
private MediaConstraintsHelper
{
public:
MediaEngineDefaultVideoSource();
void Shutdown() override {};
+ void ReleaseInterfaces() override {};
void GetName(nsAString&) override;
void GetUUID(nsACString&) override;
nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
const MediaEnginePrefs &aPrefs,
const nsString& aDeviceId,
const nsACString& aOrigin) override;
@@ -104,16 +105,17 @@ class SineWaveGenerator;
class MediaEngineDefaultAudioSource : public nsITimerCallback,
public MediaEngineAudioSource,
private MediaConstraintsHelper
{
public:
MediaEngineDefaultAudioSource();
void Shutdown() override {};
+ void ReleaseInterfaces() override {};
void GetName(nsAString&) override;
void GetUUID(nsACString&) override;
nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
const MediaEnginePrefs &aPrefs,
const nsString& aDeviceId,
const nsACString& aOrigin) override;
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.h
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.h
@@ -91,16 +91,17 @@ public:
bool ChooseCapability(const dom::MediaTrackConstraints &aConstraints,
const MediaEnginePrefs &aPrefs,
const nsString& aDeviceId) override;
void Refresh(int aIndex);
void Shutdown() override;
+ void ReleaseInterfaces() override {}
protected:
~MediaEngineRemoteVideoSource() { Shutdown(); }
private:
// Initialize the needed Video engine interfaces.
void Init();
size_t NumCapabilities() override;
--- a/dom/media/webrtc/MediaEngineTabVideoSource.h
+++ b/dom/media/webrtc/MediaEngineTabVideoSource.h
@@ -14,16 +14,17 @@ namespace mozilla {
class MediaEngineTabVideoSource : public MediaEngineVideoSource, nsIDOMEventListener, nsITimerCallback {
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIDOMEVENTLISTENER
NS_DECL_NSITIMERCALLBACK
MediaEngineTabVideoSource();
void Shutdown() override {};
+ void ReleaseInterfaces() override {}
void GetName(nsAString_internal&) override;
void GetUUID(nsACString_internal&) override;
nsresult Allocate(const dom::MediaTrackConstraints &,
const mozilla::MediaEnginePrefs&,
const nsString& aDeviceId,
const nsACString& aOrigin) override;
nsresult Deallocate() override;
nsresult Start(mozilla::SourceMediaStream*, mozilla::TrackID) override;
--- a/dom/media/webrtc/MediaEngineWebRTC.h
+++ b/dom/media/webrtc/MediaEngineWebRTC.h
@@ -83,16 +83,17 @@ public:
{
// Nothing to do here, everything is managed in MediaManager.cpp
return NS_OK;
}
void Shutdown() override
{
// Nothing to do here, everything is managed in MediaManager.cpp
}
+ void ReleaseInterfaces() override {}
nsresult Start(SourceMediaStream* aMediaStream, TrackID aId) override;
nsresult Stop(SourceMediaStream* aMediaStream, TrackID aId) override;
nsresult Restart(const dom::MediaTrackConstraints& aConstraints,
const MediaEnginePrefs &aPrefs,
const nsString& aDeviceId) override;
void SetDirectListeners(bool aDirect) override
{}
void NotifyOutputData(MediaStreamGraph* aGraph,
@@ -337,17 +338,20 @@ protected:
// Protected destructor, to discourage deletion outside of Release():
~AudioInputWebRTC() {}
};
class WebRTCAudioDataListener : public AudioDataListener
{
protected:
// Protected destructor, to discourage deletion outside of Release():
- virtual ~WebRTCAudioDataListener() {}
+ virtual ~WebRTCAudioDataListener()
+ {
+ mAudioSource->ReleaseInterfaces();
+ }
public:
explicit WebRTCAudioDataListener(MediaEngineAudioSource* aAudioSource) :
mAudioSource(aAudioSource)
{}
// AudioDataListenerInterface methods
virtual void NotifyOutputData(MediaStreamGraph* aGraph,
@@ -450,35 +454,41 @@ public:
const nsString& aDeviceId) override;
// VoEMediaProcess.
void Process(int channel, webrtc::ProcessingTypes type,
int16_t audio10ms[], int length,
int samplingFreq, bool isStereo) override;
void Shutdown() override;
+ void ReleaseInterfaces() override;
NS_DECL_THREADSAFE_ISUPPORTS
protected:
- ~MediaEngineWebRTCMicrophoneSource() { Shutdown(); }
+ ~MediaEngineWebRTCMicrophoneSource() {
+ Shutdown();
+ ReleaseInterfaces();
+ }
private:
void Init();
webrtc::VoiceEngine* mVoiceEngine;
RefPtr<mozilla::AudioInput> mAudioInput;
RefPtr<WebRTCAudioDataListener> mListener;
ScopedCustomReleasePtr<webrtc::VoEBase> mVoEBase;
ScopedCustomReleasePtr<webrtc::VoEExternalMedia> mVoERender;
ScopedCustomReleasePtr<webrtc::VoENetwork> mVoENetwork;
ScopedCustomReleasePtr<webrtc::VoEAudioProcessing> mVoEProcessing;
+ // accessed from the GraphDriver thread except for deletion
nsAutoPtr<AudioPacketizer<AudioDataValue, int16_t>> mPacketizer;
+ ScopedCustomReleasePtr<webrtc::VoEExternalMedia> mVoERenderListener;
// mMonitor protects mSources[] access/changes, and transitions of mState
// from kStarted to kStopped (which are combined with EndTrack()).
// mSources[] is accessed from webrtc threads.
Monitor mMonitor;
nsTArray<RefPtr<SourceMediaStream>> mSources;
nsCOMPtr<nsIThread> mThread;
int mCapIndex;
--- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -446,17 +446,18 @@ void
MediaEngineWebRTCMicrophoneSource::NotifyOutputData(MediaStreamGraph* aGraph,
AudioDataValue* aBuffer,
size_t aFrames,
TrackRate aRate,
uint32_t aChannels)
{
}
-// Called back on GraphDriver thread
+// Called back on GraphDriver thread!
+// Note this can be called back after ::Shutdown()
void
MediaEngineWebRTCMicrophoneSource::NotifyInputData(MediaStreamGraph* aGraph,
const AudioDataValue* aBuffer,
size_t aFrames,
TrackRate aRate,
uint32_t aChannels)
{
// This will call Process() with data coming out of the AEC/NS/AGC/etc chain
@@ -585,27 +586,32 @@ MediaEngineWebRTCMicrophoneSource::Shutd
if (mState == kAllocated || mState == kStopped) {
Deallocate();
}
mVoEBase->Terminate();
if (mChannel != -1) {
mVoENetwork->DeRegisterExternalTransport(mChannel);
}
+ // Don't release the webrtc.org pointers yet until the Listener is (async) shutdown
+ mListener = nullptr; // breaks a cycle, since the WebRTCAudioDataListener has a RefPtr to us
+}
+void
+MediaEngineWebRTCMicrophoneSource::ReleaseInterfaces()
+{
delete mNullTransport;
mNullTransport = nullptr;
mVoEProcessing = nullptr;
mVoENetwork = nullptr;
mVoERender = nullptr;
mVoEBase = nullptr;
mAudioInput = nullptr;
- mListener = nullptr; // breaks a cycle, since the WebRTCAudioDataListener has a RefPtr to us
mState = kReleased;
mInitDone = false;
}
typedef int16_t sample;
void