2015-08-31 15:51:29 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set sw=2 ts=8 et ft=cpp : */
|
2012-07-12 15:53:08 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
Bug 1299515 - Flatten MediaEngineSource class hierarchy. r=jib
The scope of flattening this hierarchy quickly grows large, so this patch does
a couple more things:
- Creates a pure interface MediaEngineSourceInterface and a base class
MediaEngineSource with common defaults and refcount support (no state!)
- Breaks out some of the helper classes to dedicated files, e.g.,
AllocationHandle, MediaEnginePrefs.
- Clarifies the threading model (written on one thread *and* under lock,
read under either)
- Fixes style, indentation, include-sorting in the affected files
- Adds comments, especially for clarifying what responsibilities methods have,
and thread usage of class members
- Changes Monitors to Mutexes since we only use them as Mutexes anyhow
- Makes MediaEngineRemoteVideoSource no longer a shared source since we now
support scaling in this source and CamerasChild can act as a broker of frames.
This greatly simplifies it. The only shared source is now
MediaEngineWebRTCMicrophoneSource, so the sharing specific common methods have
been moved to that source.
MozReview-Commit-ID: KeVZQo6gLm2
--HG--
rename : dom/media/webrtc/MediaEngine.h => dom/media/webrtc/MediaEnginePrefs.h
extra : rebase_source : c785a5feb896312912170475d6b8d997e712e48f
2018-01-24 18:49:13 +03:00
|
|
|
#include "MediaEngineWebRTC.h"
|
2013-02-20 19:18:54 +04:00
|
|
|
|
Bug 1299515 - Flatten MediaEngineSource class hierarchy. r=jib
The scope of flattening this hierarchy quickly grows large, so this patch does
a couple more things:
- Creates a pure interface MediaEngineSourceInterface and a base class
MediaEngineSource with common defaults and refcount support (no state!)
- Breaks out some of the helper classes to dedicated files, e.g.,
AllocationHandle, MediaEnginePrefs.
- Clarifies the threading model (written on one thread *and* under lock,
read under either)
- Fixes style, indentation, include-sorting in the affected files
- Adds comments, especially for clarifying what responsibilities methods have,
and thread usage of class members
- Changes Monitors to Mutexes since we only use them as Mutexes anyhow
- Makes MediaEngineRemoteVideoSource no longer a shared source since we now
support scaling in this source and CamerasChild can act as a broker of frames.
This greatly simplifies it. The only shared source is now
MediaEngineWebRTCMicrophoneSource, so the sharing specific common methods have
been moved to that source.
MozReview-Commit-ID: KeVZQo6gLm2
--HG--
rename : dom/media/webrtc/MediaEngine.h => dom/media/webrtc/MediaEnginePrefs.h
extra : rebase_source : c785a5feb896312912170475d6b8d997e712e48f
2018-01-24 18:49:13 +03:00
|
|
|
#include "AllocationHandle.h"
|
|
|
|
#include "CamerasChild.h"
|
2013-01-12 03:30:20 +04:00
|
|
|
#include "CSFLog.h"
|
2014-06-27 16:23:55 +04:00
|
|
|
#include "MediaEngineTabVideoSource.h"
|
2015-08-31 15:51:29 +03:00
|
|
|
#include "MediaEngineRemoteVideoSource.h"
|
2014-04-18 23:15:10 +04:00
|
|
|
#include "MediaTrackConstraints.h"
|
2018-07-16 12:30:46 +03:00
|
|
|
#include "mozilla/dom/MediaDeviceInfo.h"
|
Bug 1299515 - Flatten MediaEngineSource class hierarchy. r=jib
The scope of flattening this hierarchy quickly grows large, so this patch does
a couple more things:
- Creates a pure interface MediaEngineSourceInterface and a base class
MediaEngineSource with common defaults and refcount support (no state!)
- Breaks out some of the helper classes to dedicated files, e.g.,
AllocationHandle, MediaEnginePrefs.
- Clarifies the threading model (written on one thread *and* under lock,
read under either)
- Fixes style, indentation, include-sorting in the affected files
- Adds comments, especially for clarifying what responsibilities methods have,
and thread usage of class members
- Changes Monitors to Mutexes since we only use them as Mutexes anyhow
- Makes MediaEngineRemoteVideoSource no longer a shared source since we now
support scaling in this source and CamerasChild can act as a broker of frames.
This greatly simplifies it. The only shared source is now
MediaEngineWebRTCMicrophoneSource, so the sharing specific common methods have
been moved to that source.
MozReview-Commit-ID: KeVZQo6gLm2
--HG--
rename : dom/media/webrtc/MediaEngine.h => dom/media/webrtc/MediaEnginePrefs.h
extra : rebase_source : c785a5feb896312912170475d6b8d997e712e48f
2018-01-24 18:49:13 +03:00
|
|
|
#include "mozilla/Logging.h"
|
|
|
|
#include "nsIComponentRegistrar.h"
|
|
|
|
#include "nsIPrefService.h"
|
|
|
|
#include "nsIPrefBranch.h"
|
|
|
|
#include "nsITabSource.h"
|
|
|
|
#include "prenv.h"
|
2013-10-18 00:48:30 +04:00
|
|
|
|
Bug 1299515 - Flatten MediaEngineSource class hierarchy. r=jib
The scope of flattening this hierarchy quickly grows large, so this patch does
a couple more things:
- Creates a pure interface MediaEngineSourceInterface and a base class
MediaEngineSource with common defaults and refcount support (no state!)
- Breaks out some of the helper classes to dedicated files, e.g.,
AllocationHandle, MediaEnginePrefs.
- Clarifies the threading model (written on one thread *and* under lock,
read under either)
- Fixes style, indentation, include-sorting in the affected files
- Adds comments, especially for clarifying what responsibilities methods have,
and thread usage of class members
- Changes Monitors to Mutexes since we only use them as Mutexes anyhow
- Makes MediaEngineRemoteVideoSource no longer a shared source since we now
support scaling in this source and CamerasChild can act as a broker of frames.
This greatly simplifies it. The only shared source is now
MediaEngineWebRTCMicrophoneSource, so the sharing specific common methods have
been moved to that source.
MozReview-Commit-ID: KeVZQo6gLm2
--HG--
rename : dom/media/webrtc/MediaEngine.h => dom/media/webrtc/MediaEnginePrefs.h
extra : rebase_source : c785a5feb896312912170475d6b8d997e712e48f
2018-01-24 18:49:13 +03:00
|
|
|
static mozilla::LazyLogModule sGetUserMediaLog("GetUserMedia");
|
2013-05-02 16:00:12 +04:00
|
|
|
#undef LOG
|
2016-05-06 16:11:17 +03:00
|
|
|
#define LOG(args) MOZ_LOG(sGetUserMediaLog, mozilla::LogLevel::Debug, args)
|
2013-05-02 16:00:12 +04:00
|
|
|
|
2012-07-12 15:53:08 +04:00
|
|
|
namespace mozilla {
|
2014-02-15 02:41:07 +04:00
|
|
|
|
2018-04-30 16:18:22 +03:00
|
|
|
using namespace CubebUtils;
|
2016-03-08 20:11:09 +03:00
|
|
|
|
2013-12-06 23:34:40 +04:00
|
|
|
MediaEngineWebRTC::MediaEngineWebRTC(MediaEnginePrefs &aPrefs)
|
2018-04-30 16:18:22 +03:00
|
|
|
: mMutex("mozilla::MediaEngineWebRTC")
|
|
|
|
, mDelayAgnostic(aPrefs.mDelayAgnostic)
|
|
|
|
, mExtendedFilter(aPrefs.mExtendedFilter)
|
|
|
|
, mHasTabVideoSource(false)
|
2013-10-18 00:48:30 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIComponentRegistrar> compMgr;
|
|
|
|
NS_GetComponentRegistrar(getter_AddRefs(compMgr));
|
|
|
|
if (compMgr) {
|
|
|
|
compMgr->IsContractIDRegistered(NS_TABSOURCESERVICE_CONTRACTID, &mHasTabVideoSource);
|
|
|
|
}
|
2016-08-11 20:04:49 +03:00
|
|
|
|
|
|
|
camera::GetChildAndCall(
|
|
|
|
&camera::CamerasChild::AddDeviceChangeCallback,
|
|
|
|
this);
|
2013-10-18 00:48:30 +04:00
|
|
|
}
|
2012-07-12 15:53:08 +04:00
|
|
|
|
2016-08-09 11:37:04 +03:00
|
|
|
void
|
|
|
|
MediaEngineWebRTC::SetFakeDeviceChangeEvents()
|
|
|
|
{
|
|
|
|
camera::GetChildAndCall(
|
|
|
|
&camera::CamerasChild::SetFakeDeviceChangeEvents);
|
|
|
|
}
|
|
|
|
|
2012-07-12 15:53:08 +04:00
|
|
|
void
|
2018-05-07 20:33:41 +03:00
|
|
|
MediaEngineWebRTC::EnumerateVideoDevices(uint64_t aWindowId,
|
|
|
|
dom::MediaSourceEnum aMediaSource,
|
2018-07-11 09:59:13 +03:00
|
|
|
nsTArray<RefPtr<MediaDevice> >* aDevices)
|
2012-07-12 15:53:08 +04:00
|
|
|
{
|
2018-05-07 20:33:41 +03:00
|
|
|
mMutex.AssertCurrentThreadOwns();
|
2013-05-02 16:00:12 +04:00
|
|
|
|
2018-05-07 20:33:41 +03:00
|
|
|
mozilla::camera::CaptureEngine capEngine = mozilla::camera::InvalidEngine;
|
2012-07-12 15:53:08 +04:00
|
|
|
|
2018-05-07 20:33:41 +03:00
|
|
|
bool scaryKind = false; // flag sources with cross-origin exploit potential
|
|
|
|
|
|
|
|
switch (aMediaSource) {
|
|
|
|
case dom::MediaSourceEnum::Window:
|
|
|
|
capEngine = mozilla::camera::WinEngine;
|
|
|
|
break;
|
|
|
|
case dom::MediaSourceEnum::Application:
|
|
|
|
capEngine = mozilla::camera::AppEngine;
|
|
|
|
break;
|
|
|
|
case dom::MediaSourceEnum::Screen:
|
|
|
|
capEngine = mozilla::camera::ScreenEngine;
|
|
|
|
scaryKind = true;
|
|
|
|
break;
|
|
|
|
case dom::MediaSourceEnum::Browser:
|
|
|
|
capEngine = mozilla::camera::BrowserEngine;
|
|
|
|
scaryKind = true;
|
|
|
|
break;
|
|
|
|
case dom::MediaSourceEnum::Camera:
|
|
|
|
capEngine = mozilla::camera::CameraEngine;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
MOZ_CRASH("No valid video engine");
|
|
|
|
break;
|
|
|
|
}
|
Bug 1299515 - Flatten MediaEngineSource class hierarchy. r=jib
The scope of flattening this hierarchy quickly grows large, so this patch does
a couple more things:
- Creates a pure interface MediaEngineSourceInterface and a base class
MediaEngineSource with common defaults and refcount support (no state!)
- Breaks out some of the helper classes to dedicated files, e.g.,
AllocationHandle, MediaEnginePrefs.
- Clarifies the threading model (written on one thread *and* under lock,
read under either)
- Fixes style, indentation, include-sorting in the affected files
- Adds comments, especially for clarifying what responsibilities methods have,
and thread usage of class members
- Changes Monitors to Mutexes since we only use them as Mutexes anyhow
- Makes MediaEngineRemoteVideoSource no longer a shared source since we now
support scaling in this source and CamerasChild can act as a broker of frames.
This greatly simplifies it. The only shared source is now
MediaEngineWebRTCMicrophoneSource, so the sharing specific common methods have
been moved to that source.
MozReview-Commit-ID: KeVZQo6gLm2
--HG--
rename : dom/media/webrtc/MediaEngine.h => dom/media/webrtc/MediaEnginePrefs.h
extra : rebase_source : c785a5feb896312912170475d6b8d997e712e48f
2018-01-24 18:49:13 +03:00
|
|
|
|
2018-05-07 20:33:41 +03:00
|
|
|
/*
|
|
|
|
* We still enumerate every time, in case a new device was plugged in since
|
|
|
|
* the last call. TODO: Verify that WebRTC actually does deal with hotplugging
|
|
|
|
* new devices (with or without new engine creation) and accordingly adjust.
|
|
|
|
* Enumeration is not neccessary if GIPS reports the same set of devices
|
|
|
|
* for a given instance of the engine. Likewise, if a device was plugged out,
|
|
|
|
* mVideoSources must be updated.
|
|
|
|
*/
|
|
|
|
int num;
|
|
|
|
num = mozilla::camera::GetChildAndCall(
|
|
|
|
&mozilla::camera::CamerasChild::NumberOfCaptureDevices,
|
|
|
|
capEngine);
|
|
|
|
|
|
|
|
for (int i = 0; i < num; i++) {
|
|
|
|
char deviceName[MediaEngineSource::kMaxDeviceNameLength];
|
|
|
|
char uniqueId[MediaEngineSource::kMaxUniqueIdLength];
|
|
|
|
bool scarySource = false;
|
|
|
|
|
|
|
|
// paranoia
|
|
|
|
deviceName[0] = '\0';
|
|
|
|
uniqueId[0] = '\0';
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = mozilla::camera::GetChildAndCall(
|
|
|
|
&mozilla::camera::CamerasChild::GetCaptureDevice,
|
|
|
|
capEngine,
|
|
|
|
i, deviceName,
|
|
|
|
sizeof(deviceName), uniqueId,
|
|
|
|
sizeof(uniqueId),
|
|
|
|
&scarySource);
|
|
|
|
if (error) {
|
|
|
|
LOG(("camera:GetCaptureDevice: Failed %d", error ));
|
|
|
|
continue;
|
|
|
|
}
|
2012-11-13 05:46:52 +04:00
|
|
|
#ifdef DEBUG
|
2018-05-07 20:33:41 +03:00
|
|
|
LOG((" Capture Device Index %d, Name %s", i, deviceName));
|
|
|
|
|
|
|
|
webrtc::CaptureCapability cap;
|
|
|
|
int numCaps = mozilla::camera::GetChildAndCall(
|
|
|
|
&mozilla::camera::CamerasChild::NumberOfCapabilities,
|
|
|
|
capEngine,
|
|
|
|
uniqueId);
|
|
|
|
LOG(("Number of Capabilities %d", numCaps));
|
|
|
|
for (int j = 0; j < numCaps; j++) {
|
|
|
|
if (mozilla::camera::GetChildAndCall(
|
|
|
|
&mozilla::camera::CamerasChild::GetCaptureCapability,
|
|
|
|
capEngine,
|
|
|
|
uniqueId,
|
|
|
|
j, cap) != 0) {
|
|
|
|
break;
|
2012-10-04 20:09:35 +04:00
|
|
|
}
|
2018-05-07 20:33:41 +03:00
|
|
|
LOG(("type=%d width=%d height=%d maxFPS=%d",
|
|
|
|
cap.rawType, cap.width, cap.height, cap.maxFPS ));
|
|
|
|
}
|
2012-10-04 20:09:35 +04:00
|
|
|
#endif
|
|
|
|
|
2018-05-07 20:33:41 +03:00
|
|
|
if (uniqueId[0] == '\0') {
|
|
|
|
// In case a device doesn't set uniqueId!
|
|
|
|
strncpy(uniqueId, deviceName, sizeof(uniqueId));
|
|
|
|
uniqueId[sizeof(uniqueId)-1] = '\0'; // strncpy isn't safe
|
|
|
|
}
|
2018-01-31 21:02:00 +03:00
|
|
|
|
2018-05-07 20:33:41 +03:00
|
|
|
NS_ConvertUTF8toUTF16 uuid(uniqueId);
|
|
|
|
RefPtr<MediaEngineSource> vSource;
|
2018-01-31 21:02:00 +03:00
|
|
|
|
2018-05-07 20:33:41 +03:00
|
|
|
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);
|
|
|
|
} else {
|
|
|
|
vSource = new MediaEngineRemoteVideoSource(i, capEngine, aMediaSource,
|
|
|
|
scaryKind || scarySource);
|
|
|
|
devicesForThisWindow->Put(uuid, vSource);
|
2012-10-17 04:53:55 +04:00
|
|
|
}
|
2018-07-11 09:59:13 +03:00
|
|
|
aDevices->AppendElement(MakeRefPtr<MediaDevice>(
|
|
|
|
vSource,
|
|
|
|
vSource->GetName(),
|
|
|
|
NS_ConvertUTF8toUTF16(vSource->GetUUID())));
|
2018-05-07 20:33:41 +03:00
|
|
|
}
|
2015-07-24 15:28:16 +03:00
|
|
|
|
2018-05-07 20:33:41 +03:00
|
|
|
if (mHasTabVideoSource || dom::MediaSourceEnum::Browser == aMediaSource) {
|
2018-07-11 09:59:13 +03:00
|
|
|
RefPtr<MediaEngineSource> tabVideoSource = new MediaEngineTabVideoSource();
|
|
|
|
aDevices->AppendElement(MakeRefPtr<MediaDevice>(
|
|
|
|
tabVideoSource,
|
|
|
|
tabVideoSource->GetName(),
|
|
|
|
NS_ConvertUTF8toUTF16(tabVideoSource->GetUUID())));
|
2018-05-07 20:33:41 +03:00
|
|
|
}
|
|
|
|
}
|
Bug 1299515 - Flatten MediaEngineSource class hierarchy. r=jib
The scope of flattening this hierarchy quickly grows large, so this patch does
a couple more things:
- Creates a pure interface MediaEngineSourceInterface and a base class
MediaEngineSource with common defaults and refcount support (no state!)
- Breaks out some of the helper classes to dedicated files, e.g.,
AllocationHandle, MediaEnginePrefs.
- Clarifies the threading model (written on one thread *and* under lock,
read under either)
- Fixes style, indentation, include-sorting in the affected files
- Adds comments, especially for clarifying what responsibilities methods have,
and thread usage of class members
- Changes Monitors to Mutexes since we only use them as Mutexes anyhow
- Makes MediaEngineRemoteVideoSource no longer a shared source since we now
support scaling in this source and CamerasChild can act as a broker of frames.
This greatly simplifies it. The only shared source is now
MediaEngineWebRTCMicrophoneSource, so the sharing specific common methods have
been moved to that source.
MozReview-Commit-ID: KeVZQo6gLm2
--HG--
rename : dom/media/webrtc/MediaEngine.h => dom/media/webrtc/MediaEnginePrefs.h
extra : rebase_source : c785a5feb896312912170475d6b8d997e712e48f
2018-01-24 18:49:13 +03:00
|
|
|
|
2018-05-07 20:33:41 +03:00
|
|
|
void
|
|
|
|
MediaEngineWebRTC::EnumerateMicrophoneDevices(uint64_t aWindowId,
|
2018-07-11 09:59:13 +03:00
|
|
|
nsTArray<RefPtr<MediaDevice> >* aDevices)
|
2018-05-07 20:33:41 +03:00
|
|
|
{
|
|
|
|
mMutex.AssertCurrentThreadOwns();
|
2012-07-12 15:53:08 +04:00
|
|
|
|
2018-04-30 16:18:22 +03:00
|
|
|
if (!mEnumerator) {
|
|
|
|
mEnumerator.reset(new CubebDeviceEnumerator());
|
2018-05-07 20:33:41 +03:00
|
|
|
}
|
Bug 1299515 - Flatten MediaEngineSource class hierarchy. r=jib
The scope of flattening this hierarchy quickly grows large, so this patch does
a couple more things:
- Creates a pure interface MediaEngineSourceInterface and a base class
MediaEngineSource with common defaults and refcount support (no state!)
- Breaks out some of the helper classes to dedicated files, e.g.,
AllocationHandle, MediaEnginePrefs.
- Clarifies the threading model (written on one thread *and* under lock,
read under either)
- Fixes style, indentation, include-sorting in the affected files
- Adds comments, especially for clarifying what responsibilities methods have,
and thread usage of class members
- Changes Monitors to Mutexes since we only use them as Mutexes anyhow
- Makes MediaEngineRemoteVideoSource no longer a shared source since we now
support scaling in this source and CamerasChild can act as a broker of frames.
This greatly simplifies it. The only shared source is now
MediaEngineWebRTCMicrophoneSource, so the sharing specific common methods have
been moved to that source.
MozReview-Commit-ID: KeVZQo6gLm2
--HG--
rename : dom/media/webrtc/MediaEngine.h => dom/media/webrtc/MediaEnginePrefs.h
extra : rebase_source : c785a5feb896312912170475d6b8d997e712e48f
2018-01-24 18:49:13 +03:00
|
|
|
|
2018-04-30 16:18:22 +03:00
|
|
|
nsTArray<RefPtr<AudioDeviceInfo>> devices;
|
|
|
|
mEnumerator->EnumerateAudioInputDevices(devices);
|
2018-01-31 21:02:00 +03:00
|
|
|
|
2018-04-30 16:18:22 +03:00
|
|
|
DebugOnly<bool> foundPreferredDevice = false;
|
2018-01-31 21:02:00 +03:00
|
|
|
|
2018-04-30 16:18:22 +03:00
|
|
|
for (uint32_t i = 0; i < devices.Length(); i++) {
|
|
|
|
MOZ_ASSERT(devices[i]->DeviceID());
|
|
|
|
LOG(("Cubeb device %u: type 0x%x, state 0x%x, name %s, id %p",
|
|
|
|
i,
|
|
|
|
devices[i]->Type(),
|
|
|
|
devices[i]->State(),
|
|
|
|
NS_ConvertUTF16toUTF8(devices[i]->Name()).get(),
|
|
|
|
devices[i]->DeviceID()));
|
|
|
|
|
|
|
|
if (devices[i]->State() == CUBEB_DEVICE_STATE_ENABLED) {
|
|
|
|
MOZ_ASSERT(devices[i]->Type() == CUBEB_DEVICE_TYPE_INPUT);
|
|
|
|
RefPtr<MediaEngineSource> source =
|
|
|
|
new MediaEngineWebRTCMicrophoneSource(
|
2018-05-29 16:20:47 +03:00
|
|
|
devices[i],
|
|
|
|
devices[i]->Name(),
|
|
|
|
// Lie and provide the name as UUID
|
|
|
|
NS_ConvertUTF16toUTF8(devices[i]->Name()),
|
|
|
|
devices[i]->MaxChannels(),
|
|
|
|
mDelayAgnostic,
|
|
|
|
mExtendedFilter);
|
|
|
|
RefPtr<MediaDevice> device = MakeRefPtr<MediaDevice>(
|
|
|
|
source,
|
|
|
|
source->GetName(),
|
|
|
|
NS_ConvertUTF8toUTF16(source->GetUUID()));
|
|
|
|
if (devices[i]->Preferred()) {
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (!foundPreferredDevice) {
|
|
|
|
foundPreferredDevice = true;
|
|
|
|
} else {
|
|
|
|
MOZ_ASSERT(!foundPreferredDevice,
|
|
|
|
"Found more than one preferred audio input device"
|
|
|
|
"while enumerating");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
aDevices->InsertElementAt(0, device);
|
|
|
|
} else {
|
|
|
|
aDevices->AppendElement(device);
|
|
|
|
}
|
2018-07-16 12:30:46 +03:00
|
|
|
}
|
|
|
|
}
|
2018-07-16 12:30:46 +03:00
|
|
|
}
|
|
|
|
|
2018-07-16 12:30:46 +03:00
|
|
|
void
|
|
|
|
MediaEngineWebRTC::EnumerateSpeakerDevices(uint64_t aWindowId,
|
|
|
|
nsTArray<RefPtr<MediaDevice> >* aDevices)
|
|
|
|
{
|
2018-07-16 12:30:46 +03:00
|
|
|
nsTArray<RefPtr<AudioDeviceInfo>> devices;
|
|
|
|
CubebUtils::GetDeviceCollection(devices, CubebUtils::Output);
|
|
|
|
for (auto& device : devices) {
|
|
|
|
if (device->State() == CUBEB_DEVICE_STATE_ENABLED) {
|
|
|
|
MOZ_ASSERT(device->Type() == CUBEB_DEVICE_TYPE_OUTPUT);
|
2018-05-29 16:20:47 +03:00
|
|
|
nsString uuid(device->Name());
|
2018-07-16 12:30:46 +03:00
|
|
|
// If, for example, input and output are in the same device, uuid
|
|
|
|
// would be the same for both which ends up to create the same
|
|
|
|
// deviceIDs (in JS).
|
|
|
|
uuid.Append(NS_LITERAL_STRING("_Speaker"));
|
|
|
|
aDevices->AppendElement(MakeRefPtr<MediaDevice>(
|
2018-05-29 16:20:47 +03:00
|
|
|
device->Name(),
|
2018-07-16 12:30:46 +03:00
|
|
|
dom::MediaDeviceKind::Audiooutput,
|
|
|
|
uuid));
|
|
|
|
}
|
|
|
|
}
|
2018-07-16 12:30:46 +03:00
|
|
|
}
|
|
|
|
|
2018-04-30 16:18:22 +03:00
|
|
|
|
2018-05-07 20:33:41 +03:00
|
|
|
void
|
|
|
|
MediaEngineWebRTC::EnumerateDevices(uint64_t aWindowId,
|
|
|
|
dom::MediaSourceEnum aMediaSource,
|
2018-07-16 12:30:46 +03:00
|
|
|
MediaSinkEnum aMediaSink,
|
2018-04-30 16:18:22 +03:00
|
|
|
nsTArray<RefPtr<MediaDevice>>* aDevices)
|
2018-05-07 20:33:41 +03:00
|
|
|
{
|
2018-07-16 12:30:46 +03:00
|
|
|
MOZ_ASSERT(aMediaSource != dom::MediaSourceEnum::Other ||
|
|
|
|
aMediaSink != MediaSinkEnum::Other);
|
2018-05-07 20:33:41 +03:00
|
|
|
// We spawn threads to handle gUM runnables, so we must protect the member vars
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
if (MediaEngineSource::IsVideo(aMediaSource)) {
|
2018-07-11 09:59:13 +03:00
|
|
|
EnumerateVideoDevices(aWindowId, aMediaSource, aDevices);
|
2018-05-07 20:33:41 +03:00
|
|
|
} else if (aMediaSource == dom::MediaSourceEnum::AudioCapture) {
|
|
|
|
RefPtr<MediaEngineWebRTCAudioCaptureSource> audioCaptureSource =
|
|
|
|
new MediaEngineWebRTCAudioCaptureSource(nullptr);
|
2018-07-11 09:59:13 +03:00
|
|
|
aDevices->AppendElement(MakeRefPtr<MediaDevice>(
|
|
|
|
audioCaptureSource,
|
|
|
|
audioCaptureSource->GetName(),
|
|
|
|
NS_ConvertUTF8toUTF16(audioCaptureSource->GetUUID())));
|
2018-07-16 12:30:46 +03:00
|
|
|
} else if (aMediaSource == dom::MediaSourceEnum::Microphone) {
|
2018-05-07 20:33:41 +03:00
|
|
|
MOZ_ASSERT(aMediaSource == dom::MediaSourceEnum::Microphone);
|
2018-07-11 09:59:13 +03:00
|
|
|
EnumerateMicrophoneDevices(aWindowId, aDevices);
|
2018-07-16 12:30:46 +03:00
|
|
|
}
|
2018-07-16 12:30:46 +03:00
|
|
|
|
|
|
|
if (aMediaSink == MediaSinkEnum::Speaker) {
|
|
|
|
EnumerateSpeakerDevices(aWindowId, aDevices);
|
|
|
|
}
|
2018-05-07 20:33:41 +03:00
|
|
|
}
|
|
|
|
|
2018-01-31 21:02:00 +03:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-12 15:53:08 +04:00
|
|
|
void
|
|
|
|
MediaEngineWebRTC::Shutdown()
|
|
|
|
{
|
2012-10-18 22:03:00 +04:00
|
|
|
// This is likely paranoia
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
|
2016-08-11 20:04:49 +03:00
|
|
|
if (camera::GetCamerasChildIfExists()) {
|
|
|
|
camera::GetChildAndCall(
|
|
|
|
&camera::CamerasChild::RemoveDeviceChangeCallback, this);
|
|
|
|
}
|
|
|
|
|
2015-05-29 21:28:03 +03:00
|
|
|
LOG(("%s", __FUNCTION__));
|
|
|
|
// Shutdown all the sources, since we may have dangling references to the
|
|
|
|
// sources in nsDOMUserMediaStreams waiting for GC/CC
|
2018-01-31 21:02:00 +03:00
|
|
|
ShutdownSources(mVideoSources);
|
|
|
|
ShutdownSources(mAudioSources);
|
2015-05-29 21:28:03 +03:00
|
|
|
|
2018-04-30 16:18:22 +03:00
|
|
|
mEnumerator = nullptr;
|
|
|
|
|
2015-08-31 15:51:29 +03:00
|
|
|
mozilla::camera::Shutdown();
|
2018-04-30 16:18:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
CubebDeviceEnumerator::CubebDeviceEnumerator()
|
|
|
|
: mMutex("CubebDeviceListMutex")
|
|
|
|
, mManualInvalidation(false)
|
|
|
|
{
|
|
|
|
int rv = cubeb_register_device_collection_changed(GetCubebContext(),
|
|
|
|
CUBEB_DEVICE_TYPE_INPUT,
|
|
|
|
&mozilla::CubebDeviceEnumerator::AudioDeviceListChanged_s,
|
|
|
|
this);
|
|
|
|
|
|
|
|
if (rv != CUBEB_OK) {
|
|
|
|
NS_WARNING("Could not register the audio input"
|
|
|
|
" device collection changed callback.");
|
|
|
|
mManualInvalidation = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CubebDeviceEnumerator::~CubebDeviceEnumerator()
|
|
|
|
{
|
|
|
|
int rv = cubeb_register_device_collection_changed(GetCubebContext(),
|
|
|
|
CUBEB_DEVICE_TYPE_INPUT,
|
|
|
|
nullptr,
|
|
|
|
this);
|
|
|
|
if (rv != CUBEB_OK) {
|
|
|
|
NS_WARNING("Could not unregister the audio input"
|
|
|
|
" device collection changed callback.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CubebDeviceEnumerator::EnumerateAudioInputDevices(nsTArray<RefPtr<AudioDeviceInfo>>& aOutDevices)
|
|
|
|
{
|
|
|
|
cubeb* context = GetCubebContext();
|
|
|
|
|
|
|
|
if (!context) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
|
|
|
|
if (mDevices.IsEmpty() || mManualInvalidation) {
|
2018-06-22 12:47:06 +03:00
|
|
|
mDevices.Clear();
|
2018-04-30 16:18:22 +03:00
|
|
|
CubebUtils::GetDeviceCollection(mDevices, CubebUtils::Input);
|
|
|
|
}
|
|
|
|
|
2018-06-22 12:47:06 +03:00
|
|
|
aOutDevices.Clear();
|
2018-04-30 16:18:22 +03:00
|
|
|
aOutDevices.AppendElements(mDevices);
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<AudioDeviceInfo>
|
|
|
|
CubebDeviceEnumerator::DeviceInfoFromID(CubebUtils::AudioDeviceID aID)
|
|
|
|
{
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < mDevices.Length(); i++) {
|
|
|
|
if (mDevices[i]->DeviceID() == aID) {
|
|
|
|
RefPtr<AudioDeviceInfo> other = mDevices[i];
|
|
|
|
return other.forget();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CubebDeviceEnumerator::AudioDeviceListChanged_s(cubeb* aContext, void* aUser)
|
|
|
|
{
|
|
|
|
CubebDeviceEnumerator* self = reinterpret_cast<CubebDeviceEnumerator*>(aUser);
|
|
|
|
self->AudioDeviceListChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CubebDeviceEnumerator::AudioDeviceListChanged()
|
|
|
|
{
|
|
|
|
MutexAutoLock lock(mMutex);
|
|
|
|
|
|
|
|
mDevices.Clear();
|
2012-07-12 15:53:08 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|