Bug 1434538 - Allocate per-allocation members in Allocate(). r?jib
This removes the assumption that a Start() call always follows an Allocate()
call for the same allocation.
We still assume that Start() calls come in the same order as Allocate() calls,
and that all Allocate() calls eventually get a Start() call.
This is fine, as all the paths causing Start() to not happen are related to
shutdown.
What we have to be careful with now is a call to Deallocate() where Stop()
didn't happen (because Start() didn't happen). There is probably no issue in
not cleaning up the arrays there, but we do just to stay sane.
MozReview-Commit-ID: KmfTbZaT5bA
--- a/dom/media/webrtc/MediaEngineCameraVideoSource.h
+++ b/dom/media/webrtc/MediaEngineCameraVideoSource.h
@@ -148,17 +148,16 @@ protected:
int mWidth, mHeight;
bool mInitDone;
int mCaptureIndex;
TrackID mTrackID;
webrtc::CaptureCapability mCapability;
webrtc::CaptureCapability mTargetCapability;
- uint64_t mHandleId;
mutable nsTArray<webrtc::CaptureCapability> mHardcodedCapabilities;
private:
nsString mDeviceName;
nsCString mUniqueId;
nsString mFacingMode;
};
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
@@ -87,17 +87,19 @@ MediaEngineRemoteVideoSource::Shutdown()
MOZ_ASSERT(mPrincipalHandles.IsEmpty());
MOZ_ASSERT(mTargetCapabilities.IsEmpty());
MOZ_ASSERT(mHandleIds.IsEmpty());
MOZ_ASSERT(mImages.IsEmpty());
break;
}
source = mSources[0];
}
- Stop(source, kVideoTrack); // XXX change to support multiple tracks
+ if (source) {
+ Stop(source, kVideoTrack); // XXX change to support multiple tracks
+ }
}
MOZ_ASSERT(mState == kStopped);
}
for (auto& registered : mRegisteredHandles) {
MOZ_ASSERT(mState == kAllocated || mState == kStopped);
Deallocate(registered.get());
}
@@ -137,16 +139,30 @@ MediaEngineRemoteVideoSource::Allocate(
MOZ_ASSERT(mTargetCapabilities.IsEmpty());
MOZ_ASSERT(mHandleIds.IsEmpty());
MOZ_ASSERT(mImages.IsEmpty());
LOG(("Video device %d reallocated", mCaptureIndex));
} else {
LOG(("Video device %d allocated shared", mCaptureIndex));
}
}
+
+ // Pre-allocate per-allocation members.
+ MonitorAutoLock lock(mMonitor);
+ MOZ_DIAGNOSTIC_ASSERT(*aOutHandle);
+ mSources.AppendElement();
+ mPrincipalHandles.AppendElement(PRINCIPAL_HANDLE_NONE);
+ mTargetCapabilities.AppendElement(mTargetCapability);
+ mHandleIds.AppendElement((*aOutHandle)->mId); // Key
+ mImages.AppendElement();
+
+ MOZ_DIAGNOSTIC_ASSERT(mSources.Length() == mPrincipalHandles.Length());
+ MOZ_DIAGNOSTIC_ASSERT(mSources.Length() == mTargetCapabilities.Length());
+ MOZ_DIAGNOSTIC_ASSERT(mSources.Length() == mHandleIds.Length());
+ MOZ_DIAGNOSTIC_ASSERT(mSources.Length() == mImages.Length());
return NS_OK;
}
nsresult
MediaEngineRemoteVideoSource::Deallocate(AllocationHandle* aHandle)
{
LOG((__PRETTY_FUNCTION__));
AssertIsOnOwningThread();
@@ -160,16 +176,38 @@ MediaEngineRemoteVideoSource::Deallocate
mozilla::camera::GetChildAndCall(
&mozilla::camera::CamerasChild::ReleaseCaptureDevice,
mCapEngine, mCaptureIndex);
mState = kReleased;
LOG(("Video device %d deallocated", mCaptureIndex));
} else {
LOG(("Video device %d deallocated but still in use", mCaptureIndex));
}
+
+ MOZ_DIAGNOSTIC_ASSERT(aHandle);
+ size_t i = mHandleIds.IndexOf(aHandle->mId);
+ if (i == mHandleIds.NoIndex) {
+ // Cleaned up by Stop() - this is allowed
+ return NS_OK;
+ }
+
+ MOZ_DIAGNOSTIC_ASSERT(!mSources[i],
+ "A handle id remaining at Deallocate() must not have "
+ "gotten the source assigned by Start(). "
+ "It would have been cleaned up by Stop().");
+ MOZ_ASSERT(mSources.Length() == mPrincipalHandles.Length());
+ MOZ_ASSERT(mSources.Length() == mTargetCapabilities.Length());
+ MOZ_ASSERT(mSources.Length() == mHandleIds.Length());
+ MOZ_ASSERT(mSources.Length() == mImages.Length());
+ mSources.RemoveElementAt(i);
+ mPrincipalHandles.RemoveElementAt(i);
+ mTargetCapabilities.RemoveElementAt(i);
+ mHandleIds.RemoveElementAt(i);
+ mImages.RemoveElementAt(i);
+
return NS_OK;
}
nsresult
MediaEngineRemoteVideoSource::Start(SourceMediaStream* aStream, TrackID aID,
const PrincipalHandle& aPrincipalHandle)
{
LOG((__PRETTY_FUNCTION__));
@@ -179,23 +217,28 @@ MediaEngineRemoteVideoSource::Start(Sour
return NS_ERROR_FAILURE;
}
if (!mImageContainer) {
mImageContainer =
layers::LayerManager::CreateImageContainer(layers::ImageContainer::ASYNCHRONOUS);
}
+ // This is an assumption that this Start() belongs to the first source that
+ // has not yet been assigned.
+ size_t index = mSources.IndexOf(nullptr);
+ if (index == mSources.NoIndex) {
+ MOZ_DIAGNOSTIC_ASSERT(false, "No allocation has happened for this source");
+ return NS_ERROR_FAILURE;
+ }
+
{
MonitorAutoLock lock(mMonitor);
- mSources.AppendElement(aStream);
- mPrincipalHandles.AppendElement(aPrincipalHandle);
- mTargetCapabilities.AppendElement(mTargetCapability);
- mHandleIds.AppendElement(mHandleId);
- mImages.AppendElement(nullptr);
+ mSources[index] = aStream;
+ mPrincipalHandles[index] = aPrincipalHandle;
MOZ_ASSERT(mSources.Length() == mPrincipalHandles.Length());
MOZ_ASSERT(mSources.Length() == mTargetCapabilities.Length());
MOZ_ASSERT(mSources.Length() == mHandleIds.Length());
MOZ_ASSERT(mSources.Length() == mImages.Length());
}
aStream->AddTrack(aID, 0, new VideoSegment(), SourceMediaStream::ADDTRACK_QUEUED);
@@ -218,16 +261,17 @@ MediaEngineRemoteVideoSource::Start(Sour
}
nsresult
MediaEngineRemoteVideoSource::Stop(mozilla::SourceMediaStream* aSource,
mozilla::TrackID aID)
{
LOG((__PRETTY_FUNCTION__));
AssertIsOnOwningThread();
+ MOZ_DIAGNOSTIC_ASSERT(aSource);
{
MonitorAutoLock lock(mMonitor);
// Drop any cached image so we don't start with a stale image on next
// usage. Also, gfx gets very upset if these are held until this object
// is gc'd in final-cc during shutdown (bug 1374164)
mImage = nullptr;
// we drop mImageContainer only in MediaEngineCaptureVideoSource::Shutdown()
@@ -292,17 +336,16 @@ MediaEngineRemoteVideoSource::UpdateSing
const NormalizedConstraints& aNewConstraint,
const MediaEnginePrefs& aPrefs,
const nsString& aDeviceId,
const char** aOutBadConstraint)
{
switch (mState) {
case kReleased:
MOZ_ASSERT(aHandle);
- mHandleId = aHandle->mId;
LOG(("ChooseCapability(kFitness) for mTargetCapability and mCapability ++"));
if (!ChooseCapability(aNetConstraints, aPrefs, aDeviceId, mCapability, kFitness)) {
*aOutBadConstraint = FindBadConstraint(aNetConstraints, *this, aDeviceId);
return NS_ERROR_FAILURE;
}
LOG(("ChooseCapability(kFitness) for mTargetCapability and mCapability --"));
mTargetCapability = mCapability;
@@ -317,18 +360,17 @@ MediaEngineRemoteVideoSource::UpdateSing
LOG(("Video device %d allocated", mCaptureIndex));
break;
case kAllocated:
case kStarted:
{
size_t index = mHandleIds.NoIndex;
if (aHandle) {
- mHandleId = aHandle->mId;
- index = mHandleIds.IndexOf(mHandleId);
+ index = mHandleIds.IndexOf(aHandle->mId);
}
LOG(("ChooseCapability(kFitness) for mTargetCapability ++"));
if (!ChooseCapability(aNewConstraint, aPrefs, aDeviceId, mTargetCapability,
kFitness)) {
*aOutBadConstraint = FindBadConstraint(aNewConstraint, *this, aDeviceId);
return NS_ERROR_FAILURE;
}