Bug 1430856 - Cache CaptureCapability in CapabilityCandidate. r?jib
This will lead to less ipc calls, hopefully speeding up getUserMedia for many
devices.
This also lets us inject any hardcoded capabilities into the candidateSet in
the future (read: next patch).
MozReview-Commit-ID: HjIhRK1nVA1
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
@@ -408,27 +408,28 @@ MediaEngineRemoteVideoSource::NumCapabil
// The default for devices that don't return discrete capabilities: treat
// them as supporting all capabilities orthogonally. E.g. screensharing.
// CaptureCapability defaults key values to 0, which means accept any value.
mHardcodedCapabilities.AppendElement(webrtc::CaptureCapability());
return mHardcodedCapabilities.Length(); // 1
}
-void
-MediaEngineRemoteVideoSource::GetCapability(size_t aIndex,
- webrtc::CaptureCapability& aOut) const
+webrtc::CaptureCapability
+MediaEngineRemoteVideoSource::GetCapability(size_t aIndex) const
{
AssertIsOnOwningThread();
+ webrtc::CaptureCapability result;
if (!mHardcodedCapabilities.IsEmpty()) {
MOZ_ASSERT(aIndex < mHardcodedCapabilities.Length());
- aOut = mHardcodedCapabilities.SafeElementAt(aIndex, webrtc::CaptureCapability());
+ result = mHardcodedCapabilities.SafeElementAt(aIndex, webrtc::CaptureCapability());
}
camera::GetChildAndCall(&camera::CamerasChild::GetCaptureCapability,
- mCapEngine, mUniqueId.get(), aIndex, aOut);
+ mCapEngine, mUniqueId.get(), aIndex, result);
+ return result;
}
void
MediaEngineRemoteVideoSource::Pull(const RefPtr<const AllocationHandle>& aHandle,
const RefPtr<SourceMediaStream>& aStream,
TrackID aTrackID,
StreamTime aDesiredTime,
const PrincipalHandle& aPrincipalHandle)
@@ -632,55 +633,53 @@ MediaEngineRemoteVideoSource::GetFeasibi
uint64_t(aCandidate.maxFPS ? H::FeasibilityDistance(double(aCandidate.maxFPS),
aConstraints.mFrameRate) : 0);
return uint32_t(std::min(distance, uint64_t(UINT32_MAX)));
}
// Find best capability by removing inferiors. May leave >1 of equal distance
/* static */ void
-MediaEngineRemoteVideoSource::TrimLessFitCandidates(nsTArray<CapabilityCandidate>& set)
+MediaEngineRemoteVideoSource::TrimLessFitCandidates(nsTArray<CapabilityCandidate>& aSet)
{
uint32_t best = UINT32_MAX;
- for (auto& candidate : set) {
+ for (auto& candidate : aSet) {
if (best > candidate.mDistance) {
best = candidate.mDistance;
}
}
- for (size_t i = 0; i < set.Length();) {
- if (set[i].mDistance > best) {
- set.RemoveElementAt(i);
+ for (size_t i = 0; i < aSet.Length();) {
+ if (aSet[i].mDistance > best) {
+ aSet.RemoveElementAt(i);
} else {
++i;
}
}
- MOZ_ASSERT(set.Length());
+ MOZ_ASSERT(aSet.Length());
}
uint32_t
MediaEngineRemoteVideoSource::GetBestFitnessDistance(
const nsTArray<const NormalizedConstraintSet*>& aConstraintSets,
const nsString& aDeviceId) const
{
AssertIsOnOwningThread();
size_t num = NumCapabilities();
-
nsTArray<CapabilityCandidate> candidateSet;
for (size_t i = 0; i < num; i++) {
- candidateSet.AppendElement(i);
+ candidateSet.AppendElement(CapabilityCandidate(GetCapability(i)));
}
bool first = true;
for (const NormalizedConstraintSet* ns : aConstraintSets) {
for (size_t i = 0; i < candidateSet.Length(); ) {
auto& candidate = candidateSet[i];
- webrtc::CaptureCapability cap;
- GetCapability(candidate.mIndex, cap);
- uint32_t distance = GetFitnessDistance(cap, *ns, aDeviceId);
+ uint32_t distance =
+ GetFitnessDistance(candidate.mCapability, *ns, aDeviceId);
if (distance == UINT32_MAX) {
candidateSet.RemoveElementAt(i);
} else {
++i;
if (first) {
candidate.mDistance = distance;
}
}
@@ -808,53 +807,49 @@ MediaEngineRemoteVideoSource::ChooseCapa
aCapability.maxFPS =
c.mFrameRate.Clamp(c.mFrameRate.mIdeal.valueOr(aPrefs.mFPS));
return true;
}
default:
break;
}
+ nsTArray<CapabilityCandidate> candidateSet;
size_t num = NumCapabilities();
-
- nsTArray<CapabilityCandidate> candidateSet;
for (size_t i = 0; i < num; i++) {
- candidateSet.AppendElement(i);
+ candidateSet.AppendElement(CapabilityCandidate(GetCapability(i)));
}
// First, filter capabilities by required constraints (min, max, exact).
for (size_t i = 0; i < candidateSet.Length();) {
auto& candidate = candidateSet[i];
- webrtc::CaptureCapability cap;
- GetCapability(candidate.mIndex, cap);
- candidate.mDistance = GetDistance(cap, aConstraints, aDeviceId, aCalculate);
- LogCapability("Capability", cap, candidate.mDistance);
+ candidate.mDistance =
+ GetDistance(candidate.mCapability, aConstraints, aDeviceId, aCalculate);
+ LogCapability("Capability", candidate.mCapability, candidate.mDistance);
if (candidate.mDistance == UINT32_MAX) {
candidateSet.RemoveElementAt(i);
} else {
++i;
}
}
- if (!candidateSet.Length()) {
- LOG(("failed to find capability match from %zu choices",num));
+ if (candidateSet.IsEmpty()) {
+ LOG(("failed to find capability match from %zu choices", candidateSet.Length()));
return false;
}
// Filter further with all advanced constraints (that don't overconstrain).
for (const auto &cs : aConstraints.mAdvanced) {
nsTArray<CapabilityCandidate> rejects;
for (size_t i = 0; i < candidateSet.Length();) {
- auto& candidate = candidateSet[i];
- webrtc::CaptureCapability cap;
- GetCapability(candidate.mIndex, cap);
- if (GetDistance(cap, cs, aDeviceId, aCalculate) == UINT32_MAX) {
- rejects.AppendElement(candidate);
+ if (GetDistance(candidateSet[i].mCapability,
+ cs, aDeviceId, aCalculate) == UINT32_MAX) {
+ rejects.AppendElement(candidateSet[i]);
candidateSet.RemoveElementAt(i);
} else {
++i;
}
}
if (!candidateSet.Length()) {
candidateSet.AppendElements(Move(rejects));
}
@@ -872,41 +867,39 @@ MediaEngineRemoteVideoSource::ChooseCapa
{
MediaTrackConstraintSet prefs;
prefs.mWidth.SetAsLong() = aPrefs.GetWidth();
prefs.mHeight.SetAsLong() = aPrefs.GetHeight();
prefs.mFrameRate.SetAsDouble() = aPrefs.mFPS;
NormalizedConstraintSet normPrefs(prefs, false);
for (auto& candidate : candidateSet) {
- webrtc::CaptureCapability cap;
- GetCapability(candidate.mIndex, cap);
- candidate.mDistance = GetDistance(cap, normPrefs, aDeviceId, aCalculate);
+ candidate.mDistance =
+ GetDistance(candidate.mCapability, normPrefs, aDeviceId, aCalculate);
}
TrimLessFitCandidates(candidateSet);
}
// Any remaining multiples all have the same distance, but may vary on
// format. Some formats are more desirable for certain use like WebRTC.
// E.g. I420 over RGB24 can remove a needless format conversion.
bool found = false;
for (auto& candidate : candidateSet) {
- webrtc::CaptureCapability cap;
- GetCapability(candidate.mIndex, cap);
+ const webrtc::CaptureCapability& cap = candidate.mCapability;
if (cap.rawType == webrtc::RawVideoType::kVideoI420 ||
cap.rawType == webrtc::RawVideoType::kVideoYUY2 ||
cap.rawType == webrtc::RawVideoType::kVideoYV12) {
aCapability = cap;
found = true;
break;
}
}
if (!found) {
- GetCapability(candidateSet[0].mIndex, aCapability);
+ aCapability = candidateSet[0].mCapability;
}
LogCapability("Chosen capability", aCapability, sameDistance);
return true;
}
void
MediaEngineRemoteVideoSource::GetSettings(MediaTrackSettings& aOutSettings) const
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.h
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.h
@@ -64,23 +64,24 @@ enum DistanceCalculation {
* The WebRTC implementation of the MediaEngine interface.
*/
class MediaEngineRemoteVideoSource : public MediaEngineSource,
public camera::FrameRelay
{
~MediaEngineRemoteVideoSource() = default;
struct CapabilityCandidate {
- explicit CapabilityCandidate(uint8_t index, uint32_t distance = 0)
- : mIndex(index), mDistance(distance) {}
+ explicit CapabilityCandidate(webrtc::CaptureCapability&& aCapability,
+ uint32_t aDistance = 0)
+ : mCapability(Forward<webrtc::CaptureCapability>(aCapability))
+ , mDistance(aDistance) {}
- size_t mIndex;
+ const webrtc::CaptureCapability mCapability;
uint32_t mDistance;
};
- typedef nsTArray<CapabilityCandidate> CapabilitySet;
bool ChooseCapability(const NormalizedConstraints& aConstraints,
const MediaEnginePrefs& aPrefs,
const nsString& aDeviceId,
webrtc::CaptureCapability& aCapability,
const DistanceCalculation aCalculate);
uint32_t GetDistance(const webrtc::CaptureCapability& aCandidate,
@@ -91,17 +92,17 @@ class MediaEngineRemoteVideoSource : pub
uint32_t GetFitnessDistance(const webrtc::CaptureCapability& aCandidate,
const NormalizedConstraintSet &aConstraints,
const nsString& aDeviceId) const;
uint32_t GetFeasibilityDistance(const webrtc::CaptureCapability& aCandidate,
const NormalizedConstraintSet &aConstraints,
const nsString& aDeviceId) const;
- static void TrimLessFitCandidates(CapabilitySet& set);
+ static void TrimLessFitCandidates(nsTArray<CapabilityCandidate>& aSet);
uint32_t GetBestFitnessDistance(
const nsTArray<const NormalizedConstraintSet*>& aConstraintSets,
const nsString& aDeviceId) const override;
public:
MediaEngineRemoteVideoSource(int aIndex,
camera::CaptureEngine aCapEngine,
@@ -163,22 +164,21 @@ private:
/**
* Returns the number of capabilities for the underlying device.
*
* Guaranteed to return at least one capability.
*/
size_t NumCapabilities() const;
/**
- * Fills `aOut` with the capability properties of the device capability with
- * index `aIndex`.
+ * Returns the capability with index `aIndex` for our assigned device.
*
* It is an error to call this with `aIndex >= NumCapabilities()`.
*/
- void GetCapability(size_t aIndex, webrtc::CaptureCapability& aOut) const;
+ webrtc::CaptureCapability GetCapability(size_t aIndex) const;
int mCaptureIndex;
const dom::MediaSourceEnum mMediaSource; // source of media (camera | application | screen)
const camera::CaptureEngine mCapEngine;
const bool mScary;
// mMutex protects certain members on 3 threads:
// MediaManager, Cameras IPC and MediaStreamGraph.