Bug 1213517 - Let cam access in competing tabs get closer to their ideals when a tab closes.
MozReview-Commit-ID: htWkYMm18U
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
@@ -27,17 +27,18 @@ using dom::ConstrainLongRange;
NS_IMPL_ISUPPORTS0(MediaEngineRemoteVideoSource)
MediaEngineRemoteVideoSource::MediaEngineRemoteVideoSource(
int aIndex, mozilla::camera::CaptureEngine aCapEngine,
dom::MediaSourceEnum aMediaSource, const char* aMonitorName)
: MediaEngineCameraVideoSource(aIndex, aMonitorName),
mMediaSource(aMediaSource),
- mCapEngine(aCapEngine)
+ mCapEngine(aCapEngine),
+ mInShutdown(false)
{
MOZ_ASSERT(aMediaSource != dom::MediaSourceEnum::Other);
Init();
}
void
MediaEngineRemoteVideoSource::Init()
{
@@ -63,16 +64,17 @@ MediaEngineRemoteVideoSource::Init()
void
MediaEngineRemoteVideoSource::Shutdown()
{
LOG((__PRETTY_FUNCTION__));
if (!mInitDone) {
return;
}
+ mInShutdown = true;
if (mState == kStarted) {
SourceMediaStream *source;
bool empty;
while (1) {
{
MonitorAutoLock lock(mMonitor);
empty = mSources.IsEmpty();
@@ -109,17 +111,18 @@ MediaEngineRemoteVideoSource::Allocate(
LOG((__PRETTY_FUNCTION__));
AssertIsOnOwningThread();
if (!mInitDone) {
LOG(("Init not done"));
return NS_ERROR_FAILURE;
}
- RefPtr<AllocationHandle> handle = new AllocationHandle(aConstraints, aOrigin);
+ RefPtr<AllocationHandle> handle = new AllocationHandle(aConstraints, aOrigin,
+ aPrefs, aDeviceId);
nsresult rv = UpdateNew(handle, aPrefs, aDeviceId, aOutBadConstraint);
if (NS_FAILED(rv)) {
return rv;
}
if (mState == kStarted &&
MOZ_LOG_TEST(GetMediaManagerLog(), mozilla::LogLevel::Debug)) {
MonitorAutoLock lock(mMonitor);
@@ -153,26 +156,34 @@ MediaEngineRemoteVideoSource::Deallocate
};
MOZ_ASSERT(mRegisteredHandles.Contains(handle, Comparator()));
mRegisteredHandles.RemoveElementAt(mRegisteredHandles.IndexOf(handle, 0,
Comparator()));
--mNrAllocations;
MOZ_ASSERT(mNrAllocations >= 0, "Double-deallocations are prohibited");
if (mNrAllocations == 0) {
+ MOZ_ASSERT(!mRegisteredHandles.Length());
if (mState != kStopped && mState != kAllocated) {
return NS_ERROR_FAILURE;
}
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_ASSERT(mRegisteredHandles.Length());
+ if (!mInShutdown) {
+ // Whenever constraints are removed, other parties may get closer to ideal.
+ auto& first = mRegisteredHandles[0];
+ const char* badConstraint = nullptr;
+ return UpdateRemove(first->mPrefs, first->mDeviceId, &badConstraint);
+ }
}
return NS_OK;
}
nsresult
MediaEngineRemoteVideoSource::Start(SourceMediaStream* aStream, TrackID aID,
const PrincipalHandle& aPrincipalHandle)
{
@@ -330,20 +341,20 @@ MediaEngineRemoteVideoSource::UpdateExis
this)) {
LOG(("StartCapture failed"));
return NS_ERROR_FAILURE;
}
mLastCapability = mCapability;
}
break;
- default:
- LOG(("Video device %d %s in ignored state %d", mCaptureIndex,
+ default:
+ LOG(("Video device %d %s in ignored state %d", mCaptureIndex,
(aHandle? aHandle->mOrigin.get() : ""), mState));
- break;
+ break;
}
if (aHandle && aNewConstraints) {
aHandle->mConstraints = *aNewConstraints;
}
return NS_OK;
}
void
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.h
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.h
@@ -70,23 +70,30 @@ public:
MediaEngineRemoteVideoSource(int aIndex, mozilla::camera::CaptureEngine aCapEngine,
dom::MediaSourceEnum aMediaSource,
const char* aMonitorName = "RemoteVideo.Monitor");
class AllocationHandle : public BaseAllocationHandle
{
public:
AllocationHandle(const dom::MediaTrackConstraints& aConstraints,
- const nsACString& aOrigin)
- : mConstraints(aConstraints), mOrigin(aOrigin) {}
+ const nsACString& aOrigin,
+ const MediaEnginePrefs& aPrefs,
+ const nsString& aDeviceId)
+ : mConstraints(aConstraints),
+ mOrigin(aOrigin),
+ mPrefs(aPrefs),
+ mDeviceId(aDeviceId) {}
private:
~AllocationHandle() override {}
public:
NormalizedConstraints mConstraints;
nsCString mOrigin;
+ MediaEnginePrefs mPrefs;
+ nsString mDeviceId;
};
nsresult Allocate(const dom::MediaTrackConstraints& aConstraints,
const MediaEnginePrefs& aPrefs,
const nsString& aDeviceId,
const nsACString& aOrigin,
BaseAllocationHandle** aOutHandle,
const char** aOutBadConstraint) override;
@@ -144,20 +151,28 @@ private:
nsresult
UpdateNew(AllocationHandle* aHandle,
const MediaEnginePrefs& aPrefs,
const nsString& aDeviceId,
const char** aOutBadConstraint) {
return UpdateExisting(aHandle, nullptr, aPrefs, aDeviceId, aOutBadConstraint);
}
+ nsresult
+ UpdateRemove(const MediaEnginePrefs& aPrefs,
+ const nsString& aDeviceId,
+ const char** aOutBadConstraint) {
+ return UpdateExisting(nullptr, nullptr, aPrefs, aDeviceId, aOutBadConstraint);
+ }
+
dom::MediaSourceEnum mMediaSource; // source of media (camera | application | screen)
mozilla::camera::CaptureEngine mCapEngine;
nsTArray<RefPtr<AllocationHandle>> mRegisteredHandles;
// To only restart camera when needed, we keep track previous settings.
webrtc::CaptureCapability mLastCapability;
+ bool mInShutdown;
};
}
#endif /* MEDIAENGINE_REMOTE_VIDEO_SOURCE_H_ */