Bug 1430856 - Default to two default capabilities when a camera can handle anything. r=jib

If a camera returns no capabilities we interpret it as it being able to handle
any capability we throw at it. However, we also end up trying to start it with
the default capability of 0x0@0. This often works, but we can crash when
rescaling it to the chosen target capability 0x0@0.

With this patch we inject up to two default capabilities, one at 640x480@30 and
one at 1280x720@30. With constraints present we'll try to adjust these defaults
so they fit within the constraints while at the same time preserve the
aspect ratio given by prefs.

MozReview-Commit-ID: 3mr7Li5TTbV

--HG--
extra : rebase_source : c525c2fd8d60f5dece548216caefc4976e9afb0b
This commit is contained in:
Andreas Pehrson 2018-02-13 20:22:18 +01:00
Родитель 7186f8d0f3
Коммит f5d34fea0d
2 изменённых файлов: 58 добавлений и 0 удалений

Просмотреть файл

@ -818,6 +818,55 @@ MediaEngineRemoteVideoSource::ChooseCapability(
candidateSet.AppendElement(CapabilityCandidate(GetCapability(i)));
}
if (!mHardcodedCapabilities.IsEmpty() &&
mMediaSource == MediaSourceEnum::Camera) {
// We have a hardcoded capability, which means this camera didn't report
// discrete capabilities. It might still allow a ranged capability, so we
// add a couple of default candidates based on prefs and constraints.
// The chosen candidate will be propagated to StartCapture() which will fail
// for an invalid candidate.
MOZ_DIAGNOSTIC_ASSERT(mHardcodedCapabilities.Length() == 1);
MOZ_DIAGNOSTIC_ASSERT(candidateSet.Length() == 1);
candidateSet.Clear();
FlattenedConstraints c(aConstraints);
// Reuse the code across both the low-definition (`false`) pref and
// the high-definition (`true`) pref.
// If there are constraints we try to satisfy them but we default to prefs.
// Note that since constraints are from content and can literally be
// anything we put (rather generous) caps on them.
for (bool isHd : {false, true}) {
webrtc::CaptureCapability cap;
int32_t prefWidth = aPrefs.GetWidth(isHd);
int32_t prefHeight = aPrefs.GetHeight(isHd);
cap.width = c.mWidth.Get(prefWidth);
cap.width = std::max(0, std::min(cap.width, 7680));
cap.height = c.mHeight.Get(prefHeight);
cap.height = std::max(0, std::min(cap.height, 4320));
cap.maxFPS = c.mFrameRate.Get(aPrefs.mFPS);
cap.maxFPS = std::max(0, std::min(cap.maxFPS, 480));
if (cap.width != prefWidth) {
// Width was affected by constraints.
// We'll adjust the height too so the aspect ratio is retained.
cap.height = cap.width * prefHeight / prefWidth;
} else if (cap.height != prefHeight) {
// Height was affected by constraints but not width.
// We'll adjust the width too so the aspect ratio is retained.
cap.width = cap.height * prefWidth / prefHeight;
}
if (candidateSet.Contains(cap, CapabilityComparator())) {
continue;
}
LogCapability("Hardcoded capability", cap, 0);
candidateSet.AppendElement(CapabilityCandidate(Move(cap)));
}
}
// First, filter capabilities by required constraints (min, max, exact).
for (size_t i = 0; i < candidateSet.Length();) {

Просмотреть файл

@ -78,6 +78,15 @@ class MediaEngineRemoteVideoSource : public MediaEngineSource,
uint32_t mDistance;
};
class CapabilityComparator {
public:
bool Equals(const CapabilityCandidate& aCandidate,
const webrtc::CaptureCapability& aCapability) const
{
return aCandidate.mCapability == aCapability;
}
};
bool ChooseCapability(const NormalizedConstraints& aConstraints,
const MediaEnginePrefs& aPrefs,
const nsString& aDeviceId,