Bug 1434600 - Add a method to clean up by window ID, on a MediaEngine. r=pehrsons

MozReview-Commit-ID: 12w4StZE2eg

--HG--
extra : rebase_source : 3c3ddf24da24e42e53d9e5352cb83945c97ead99
This commit is contained in:
Paul Adenot 2018-01-31 19:02:00 +01:00
parent 4bf54def7a
commit 8413544b59
5 changed files with 130 additions and 33 deletions

View File

@ -48,6 +48,7 @@ public:
dom::MediaSourceEnum,
nsTArray<RefPtr<MediaEngineSource>>*) = 0;
virtual void ReleaseResourcesForWindow(uint64_t aWindowId) = 0;
virtual void Shutdown() = 0;
virtual void SetFakeDeviceChangeEvents() {}

View File

@ -561,13 +561,18 @@ MediaEngineDefault::EnumerateDevices(uint64_t aWindowId,
// We once had code here to find a VideoSource with the same settings and
// re-use that. This is no longer possible since the resolution gets set
// in Allocate().
nsTArray<RefPtr<MediaEngineSource>>*
devicesForThisWindow = mVSources.LookupOrAdd(aWindowId);
auto newSource = MakeRefPtr<MediaEngineDefaultVideoSource>();
mVSources.AppendElement(newSource);
devicesForThisWindow->AppendElement(newSource);
aSources->AppendElement(newSource);
return;
}
case dom::MediaSourceEnum::Microphone: {
for (const RefPtr<MediaEngineDefaultAudioSource>& source : mASources) {
nsTArray<RefPtr<MediaEngineDefaultAudioSource>>*
devicesForThisWindow = mASources.LookupOrAdd(aWindowId);
for (const RefPtr<MediaEngineDefaultAudioSource>& source : *devicesForThisWindow) {
if (source->IsAvailable()) {
aSources->AppendElement(source);
}
@ -576,7 +581,7 @@ MediaEngineDefault::EnumerateDevices(uint64_t aWindowId,
if (aSources->IsEmpty()) {
// All streams are currently busy, just make a new one.
auto newSource = MakeRefPtr<MediaEngineDefaultAudioSource>();
mASources.AppendElement(newSource);
devicesForThisWindow->AppendElement(newSource);
aSources->AppendElement(newSource);
}
return;
@ -587,16 +592,52 @@ MediaEngineDefault::EnumerateDevices(uint64_t aWindowId,
}
}
void
MediaEngineDefault::ReleaseResourcesForWindow(uint64_t aWindowId)
{
nsTArray<RefPtr<MediaEngineDefaultAudioSource>>* audioDevicesForThisWindow =
mASources.Get(aWindowId);
if (audioDevicesForThisWindow) {
for (const RefPtr<MediaEngineDefaultAudioSource>& source :
*audioDevicesForThisWindow) {
source->Shutdown();
}
}
mASources.Remove(aWindowId);
nsTArray<RefPtr<MediaEngineSource>>* videoDevicesForThisWindow =
mVSources.Get(aWindowId);
if (videoDevicesForThisWindow) {
for (const RefPtr<MediaEngineSource>& source :
*videoDevicesForThisWindow) {
source->Shutdown();
}
}
mVSources.Remove(aWindowId);
}
void
MediaEngineDefault::Shutdown()
{
AssertIsOnOwningThread();
for (RefPtr<MediaEngineDefaultVideoSource>& source : mVSources) {
source->Shutdown();
for (auto iter = mVSources.Iter(); !iter.Done(); iter.Next()) {
for (const RefPtr<MediaEngineSource>& source : *iter.UserData()) {
if (source) {
source->Shutdown();
}
}
}
for (RefPtr<MediaEngineDefaultAudioSource>& source : mASources) {
source->Shutdown();
for (auto iter = mASources.Iter(); !iter.Done(); iter.Next()) {
for (const RefPtr<MediaEngineDefaultAudioSource>& source : *iter.UserData()) {
if (source) {
source->Shutdown();
}
}
}
mVSources.Clear();
mASources.Clear();

View File

@ -191,12 +191,16 @@ public:
dom::MediaSourceEnum,
nsTArray<RefPtr<MediaEngineSource>>*) override;
void Shutdown() override;
void ReleaseResourcesForWindow(uint64_t aWindowId) override;
private:
~MediaEngineDefault() = default;
nsTArray<RefPtr<MediaEngineDefaultVideoSource>> mVSources;
nsTArray<RefPtr<MediaEngineDefaultAudioSource>> mASources;
// WindowID -> Array of devices.
nsClassHashtable<nsUint64HashKey,
nsTArray<RefPtr<MediaEngineSource>>> mVSources;
nsClassHashtable<nsUint64HashKey,
nsTArray<RefPtr<MediaEngineDefaultAudioSource>>> mASources;
};
} // namespace mozilla

View File

@ -238,15 +238,20 @@ MediaEngineWebRTC::EnumerateDevices(uint64_t aWindowId,
}
NS_ConvertUTF8toUTF16 uuid(uniqueId);
RefPtr<MediaEngineSource> vSource = mVideoSources.Get(uuid);
if (vSource && vSource->RequiresSharing()) {
RefPtr<MediaEngineSource> vSource;
nsRefPtrHashtable<nsStringHashKey, MediaEngineSource>*
devicesForThisWindow = mVideoSources.LookupOrAdd(aWindowId);
if (devicesForThisWindow->Get(uuid, getter_AddRefs(vSource)) &&
vSource->RequiresSharing()) {
// We've already seen this shared device, just refresh and append.
static_cast<MediaEngineRemoteVideoSource*>(vSource.get())->Refresh(i);
aSources->AppendElement(vSource.get());
} else {
vSource = new MediaEngineRemoteVideoSource(i, capEngine, aMediaSource,
scaryKind || scarySource);
mVideoSources.Put(uuid, vSource);
devicesForThisWindow->Put(uuid, vSource);
aSources->AppendElement(vSource);
}
}
@ -300,9 +305,15 @@ MediaEngineWebRTC::EnumerateDevices(uint64_t aWindowId,
strcpy(uniqueId, deviceName); // safe given assert and initialization/error-check
}
RefPtr<MediaEngineSource> aSource;
NS_ConvertUTF8toUTF16 uuid(uniqueId);
RefPtr<MediaEngineSource> aSource = mAudioSources.Get(uuid);
if (aSource && aSource->RequiresSharing()) {
nsRefPtrHashtable<nsStringHashKey, MediaEngineSource>*
devicesForThisWindow = mAudioSources.LookupOrAdd(aWindowId);
if (devicesForThisWindow->Get(uuid, getter_AddRefs(aSource)) &&
aSource->RequiresSharing()) {
// We've already seen this device, just append.
aSources->AppendElement(aSource.get());
} else {
@ -310,7 +321,7 @@ MediaEngineWebRTC::EnumerateDevices(uint64_t aWindowId,
new mozilla::AudioInputCubeb(i),
i, deviceName, uniqueId,
mDelayAgnostic, mExtendedFilter);
mAudioSources.Put(uuid, aSource); // Hashtable takes ownership.
devicesForThisWindow->Put(uuid, aSource);
aSources->AppendElement(aSource);
}
}
@ -323,6 +334,53 @@ MediaEngineWebRTC::SupportsDuplex()
return mFullDuplex;
}
void
MediaEngineWebRTC::ReleaseResourcesForWindow(uint64_t aWindowId)
{
{
nsRefPtrHashtable<nsStringHashKey, MediaEngineSource>*
audioDevicesForThisWindow = mAudioSources.Get(aWindowId);
if (audioDevicesForThisWindow) {
for (auto iter = audioDevicesForThisWindow->Iter(); !iter.Done();
iter.Next()) {
iter.UserData()->Shutdown();
}
// This makes audioDevicesForThisWindow invalid.
mAudioSources.Remove(aWindowId);
}
}
{
nsRefPtrHashtable<nsStringHashKey, MediaEngineSource>*
videoDevicesForThisWindow = mVideoSources.Get(aWindowId);
if (videoDevicesForThisWindow) {
for (auto iter = videoDevicesForThisWindow->Iter(); !iter.Done();
iter.Next()) {
iter.UserData()->Shutdown();
}
// This makes videoDevicesForThisWindow invalid.
mVideoSources.Remove(aWindowId);
}
}
}
namespace {
template<typename T>
void ShutdownSources(T& aHashTable)
{
for (auto iter = aHashTable.Iter(); !iter.Done(); iter.Next()) {
for (auto iterInner = iter.UserData()->Iter(); !iterInner.Done();
iterInner.Next()) {
MediaEngineSource* source = iterInner.UserData();
source->Shutdown();
}
}
}
}
void
MediaEngineWebRTC::Shutdown()
{
@ -337,20 +395,8 @@ MediaEngineWebRTC::Shutdown()
LOG(("%s", __FUNCTION__));
// Shutdown all the sources, since we may have dangling references to the
// sources in nsDOMUserMediaStreams waiting for GC/CC
for (auto iter = mVideoSources.Iter(); !iter.Done(); iter.Next()) {
MediaEngineSource* source = iter.UserData();
if (source) {
source->Shutdown();
}
}
for (auto iter = mAudioSources.Iter(); !iter.Done(); iter.Next()) {
MediaEngineSource* source = iter.UserData();
if (source) {
source->Shutdown();
}
}
mVideoSources.Clear();
mAudioSources.Clear();
ShutdownSources(mVideoSources);
ShutdownSources(mAudioSources);
mozilla::camera::Shutdown();
AudioInputCubeb::CleanupGlobalData();

View File

@ -621,6 +621,7 @@ public:
void EnumerateDevices(uint64_t aWindowId,
dom::MediaSourceEnum,
nsTArray<RefPtr<MediaEngineSource>>*) override;
void ReleaseResourcesForWindow(uint64_t aWindowId) override;
private:
~MediaEngineWebRTC() = default;
@ -634,10 +635,14 @@ private:
bool mExtendedFilter;
bool mHasTabVideoSource;
// Store devices we've already seen in a hashtable for quick return.
// Maps UUID to MediaEngineSource (one set for audio, one for video).
nsRefPtrHashtable<nsStringHashKey, MediaEngineSource> mVideoSources;
nsRefPtrHashtable<nsStringHashKey, MediaEngineSource> mAudioSources;
// Maps WindowID to a map of device uuid to their MediaEngineSource,
// separately for audio and video.
nsClassHashtable<nsUint64HashKey,
nsRefPtrHashtable<nsStringHashKey,
MediaEngineSource>> mVideoSources;
nsClassHashtable<nsUint64HashKey,
nsRefPtrHashtable<nsStringHashKey,
MediaEngineSource>> mAudioSources;
};
}