зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1364038
- Call SourceListener::StopTrack when the coresponding external device is disconnected. r=jib
MozReview-Commit-ID: EfpmXBJf7PP --HG-- extra : rebase_source : 328b146ba3531f10a36147f820e84f4d8402ff8a
This commit is contained in:
Родитель
dfb597110e
Коммит
dc857a8098
|
@ -530,6 +530,8 @@ public:
|
|||
|
||||
void StopSharing();
|
||||
|
||||
void StopRawID(const nsString& removedDeviceID);
|
||||
|
||||
/**
|
||||
* Called by one of our SourceListeners when one of its tracks has stopped.
|
||||
* Schedules an event for the next stable state to update chrome.
|
||||
|
@ -1728,6 +1730,8 @@ MediaManager::EnumerateRawDevices(uint64_t aWindowId,
|
|||
if ((!fakeCams && hasVideo) || (!fakeMics && hasAudio)) {
|
||||
RefPtr<MediaManager> manager = MediaManager_GetInstance();
|
||||
realBackend = manager->GetBackend(aWindowId);
|
||||
// We need to listen to this event even JS didn't listen to it.
|
||||
realBackend->AddDeviceChangeCallback(manager);
|
||||
}
|
||||
|
||||
auto result = MakeUnique<SourceSet>();
|
||||
|
@ -2037,7 +2041,6 @@ int MediaManager::AddDeviceChangeCallback(DeviceChangeCallback* aCallback)
|
|||
bool fakeDeviceChangeEventOn = mPrefs.mFakeDeviceChangeEventOn;
|
||||
MediaManager::PostTask(NewTaskFrom([fakeDeviceChangeEventOn]() {
|
||||
RefPtr<MediaManager> manager = MediaManager_GetInstance();
|
||||
manager->GetBackend(0)->AddDeviceChangeCallback(manager);
|
||||
if (fakeDeviceChangeEventOn)
|
||||
manager->GetBackend(0)->SetFakeDeviceChangeEvents();
|
||||
}));
|
||||
|
@ -2045,11 +2048,61 @@ int MediaManager::AddDeviceChangeCallback(DeviceChangeCallback* aCallback)
|
|||
return DeviceChangeCallback::AddDeviceChangeCallback(aCallback);
|
||||
}
|
||||
|
||||
static void
|
||||
StopRawIDCallback(MediaManager *aThis,
|
||||
uint64_t aWindowID,
|
||||
GetUserMediaWindowListener *aListener,
|
||||
void *aData)
|
||||
{
|
||||
if (!aListener || !aData) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsString* removedDeviceID = static_cast<nsString*>(aData);
|
||||
aListener->StopRawID(*removedDeviceID);
|
||||
}
|
||||
|
||||
|
||||
void MediaManager::OnDeviceChange() {
|
||||
RefPtr<MediaManager> self(this);
|
||||
NS_DispatchToMainThread(media::NewRunnableFrom([self,this]() mutable {
|
||||
NS_DispatchToMainThread(media::NewRunnableFrom([self]() mutable {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
DeviceChangeCallback::OnDeviceChange();
|
||||
self->DeviceChangeCallback::OnDeviceChange();
|
||||
|
||||
// On some Windows machine, if we call EnumertaeRawDevices immediately after receiving
|
||||
// devicechange event, sometimes we would get outdated devices list.
|
||||
PR_Sleep(PR_MillisecondsToInterval(100));
|
||||
RefPtr<PledgeSourceSet> p = self->EnumerateRawDevices(0, MediaSourceEnum::Camera, MediaSourceEnum::Microphone, false);
|
||||
p->Then([self](SourceSet*& aDevices) mutable {
|
||||
UniquePtr<SourceSet> devices(aDevices);
|
||||
nsTArray<nsString> deviceIDs;
|
||||
|
||||
for (auto& device : *devices) {
|
||||
nsString id;
|
||||
device->GetId(id);
|
||||
id.ReplaceSubstring(NS_LITERAL_STRING("default: "), NS_LITERAL_STRING(""));
|
||||
if (!deviceIDs.Contains(id)) {
|
||||
deviceIDs.AppendElement(id);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& id : self->mDeviceIDs) {
|
||||
if (!deviceIDs.Contains(id)) {
|
||||
// Stop the coresponding SourceListener
|
||||
nsGlobalWindow::WindowByIdTable* windowsById = nsGlobalWindow::GetWindowsTable();
|
||||
if (windowsById) {
|
||||
for (auto iter = windowsById->Iter(); !iter.Done(); iter.Next()) {
|
||||
nsGlobalWindow* window = iter.Data();
|
||||
if (window->IsInnerWindow()) {
|
||||
self->IterateWindowListeners(window->AsInner(), StopRawIDCallback, &id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self->mDeviceIDs = deviceIDs;
|
||||
}, [](MediaStreamError*& reason) {});
|
||||
return NS_OK;
|
||||
}));
|
||||
}
|
||||
|
@ -2658,6 +2711,17 @@ MediaManager::EnumerateDevicesImpl(uint64_t aWindowId,
|
|||
if (!mgr) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mgr->mDeviceIDs.Clear();
|
||||
for (auto& device : *devices) {
|
||||
nsString id;
|
||||
device->GetId(id);
|
||||
id.ReplaceSubstring(NS_LITERAL_STRING("default: "), NS_LITERAL_STRING(""));
|
||||
if (!mgr->mDeviceIDs.Contains(id)) {
|
||||
mgr->mDeviceIDs.AppendElement(id);
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<PledgeSourceSet> p = mgr->mOutstandingPledges.Remove(id);
|
||||
if (!p || !mgr->IsWindowStillActive(aWindowId)) {
|
||||
return NS_OK;
|
||||
|
@ -2985,6 +3049,7 @@ MediaManager::Shutdown()
|
|||
mActiveCallbacks.Clear();
|
||||
mCallIds.Clear();
|
||||
mPendingGUMRequest.Clear();
|
||||
mDeviceIDs.Clear();
|
||||
#ifdef MOZ_WEBRTC
|
||||
StopWebRtcLog();
|
||||
#endif
|
||||
|
@ -3975,6 +4040,29 @@ GetUserMediaWindowListener::StopSharing()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
GetUserMediaWindowListener::StopRawID(const nsString& removedDeviceID)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
for (auto& source : mActiveListeners) {
|
||||
if (source->GetAudioDevice()) {
|
||||
nsString id;
|
||||
source->GetAudioDevice()->GetRawId(id);
|
||||
if (removedDeviceID.Equals(id)) {
|
||||
source->Stop();
|
||||
}
|
||||
}
|
||||
if (source->GetVideoDevice()) {
|
||||
nsString id;
|
||||
source->GetVideoDevice()->GetRawId(id);
|
||||
if (removedDeviceID.Equals(id)) {
|
||||
source->Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GetUserMediaWindowListener::NotifySourceTrackStopped()
|
||||
{
|
||||
|
|
|
@ -334,6 +334,7 @@ private:
|
|||
media::CoatCheck<PledgeSourceSet> mOutstandingPledges;
|
||||
media::CoatCheck<PledgeChar> mOutstandingCharPledges;
|
||||
media::CoatCheck<PledgeVoid> mOutstandingVoidPledges;
|
||||
nsTArray<nsString> mDeviceIDs;
|
||||
public:
|
||||
media::CoatCheck<media::Pledge<nsCString>> mGetPrincipalKeyPledges;
|
||||
RefPtr<media::Parent<media::NonE10s>> mNonE10sParent;
|
||||
|
|
Загрузка…
Ссылка в новой задаче