--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -328,21 +328,18 @@ public:
if (mAudioDevice) {
mAudioDevice->GetSource()->Stop(source, kAudioTrack);
mAudioDevice->GetSource()->Deallocate();
}
if (mVideoDevice) {
mVideoDevice->GetSource()->Stop(source, kVideoTrack);
mVideoDevice->GetSource()->Deallocate();
}
- // We consider ourselves finished if all tracks have been stopped, as
- // there is no way to restart them from the JS APIs.
- if (mBool || ((!mAudioDevice || mAudioDevice->GetSource()->IsAvailable()) &&
- (!mVideoDevice || mVideoDevice->GetSource()->IsAvailable()))) {
- source->Finish();
+ if (mType == MEDIA_STOP) {
+ source->EndAllTrackAndFinish();
}
nsIRunnable *event =
new GetUserMediaNotificationEvent(mListener,
mType == MEDIA_STOP ?
GetUserMediaNotificationEvent::STOPPING :
GetUserMediaNotificationEvent::STOPPED_TRACK,
mAudioDevice != nullptr,
@@ -2390,35 +2387,35 @@ StopSharingCallback(MediaManager *aThis,
{
MOZ_ASSERT(NS_IsMainThread());
if (aListeners) {
auto length = aListeners->Length();
for (size_t i = 0; i < length; ++i) {
GetUserMediaCallbackMediaStreamListener *listener = aListeners->ElementAt(i);
if (listener->Stream()) { // aka HasBeenActivate()ed
- listener->Invalidate();
+ listener->Stop();
}
listener->Remove();
listener->StopSharing();
}
aListeners->Clear();
aThis->RemoveWindowID(aWindowID);
}
}
void
MediaManager::OnNavigation(uint64_t aWindowID)
{
MOZ_ASSERT(NS_IsMainThread());
LOG(("OnNavigation for %llu", aWindowID));
- // Invalidate this window. The runnables check this value before making
- // a call to content.
+ // Stop the streams for this window. The runnables check this value before
+ // making a call to content.
nsTArray<nsString>* callIDs;
if (mCallIds.Get(aWindowID, &callIDs)) {
for (auto& callID : *callIDs) {
mActiveCallbacks.Remove(callID);
}
mCallIds.Remove(aWindowID);
}
@@ -3037,56 +3034,49 @@ MediaManager::IsActivelyCapturingOrHasAP
return false;
}
}
return audio == nsIPermissionManager::ALLOW_ACTION ||
video == nsIPermissionManager::ALLOW_ACTION;
}
void
-GetUserMediaCallbackMediaStreamListener::Invalidate()
+GetUserMediaCallbackMediaStreamListener::Stop()
{
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread");
if (mStopped) {
return;
}
// We can't take a chance on blocking here, so proxy this to another
// thread.
// Pass a ref to us (which is threadsafe) so it can query us for the
// source stream info.
MediaManager::PostTask(FROM_HERE,
new MediaOperationTask(MEDIA_STOP,
this, nullptr, nullptr,
!mAudioStopped ? mAudioDevice.get() : nullptr,
!mVideoStopped ? mVideoDevice.get() : nullptr,
- mFinished, mWindowID, nullptr));
+ false, mWindowID, nullptr));
mStopped = mAudioStopped = mVideoStopped = true;
}
// Doesn't kill audio
void
GetUserMediaCallbackMediaStreamListener::StopSharing()
{
MOZ_ASSERT(NS_IsMainThread());
- if (mVideoDevice && !mStopped &&
+ if (mVideoDevice &&
(mVideoDevice->GetMediaSource() == dom::MediaSourceEnum::Screen ||
mVideoDevice->GetMediaSource() == dom::MediaSourceEnum::Application ||
mVideoDevice->GetMediaSource() == dom::MediaSourceEnum::Window)) {
- // Stop the whole stream if there's no audio; just the video track if we have both
- if (!mAudioDevice) {
- Invalidate();
- } else if (!mVideoStopped) {
- MediaManager::PostTask(FROM_HERE,
- new MediaOperationTask(MEDIA_STOP_TRACK,
- this, nullptr, nullptr,
- nullptr, mVideoDevice,
- mFinished, mWindowID, nullptr));
- mVideoStopped = true;
- }
+ // We want to stop the whole stream if there's no audio;
+ // just the video track if we have both.
+ // StopTrack figures this out for us.
+ StopTrack(kVideoTrack);
} else if (mAudioDevice &&
mAudioDevice->GetMediaSource() == dom::MediaSourceEnum::AudioCapture) {
nsCOMPtr<nsPIDOMWindowInner> window = nsGlobalWindow::GetInnerWindowWithId(mWindowID)->AsInner();
MOZ_ASSERT(window);
window->SetAudioCapture(false);
MediaStreamGraph* graph =
MediaStreamGraph::GetInstance(MediaStreamGraph::AUDIO_THREAD_DRIVER,
dom::AudioChannel::Normal);
@@ -3189,43 +3179,58 @@ GetUserMediaCallbackMediaStreamListener:
}
// Stop backend for track
void
GetUserMediaCallbackMediaStreamListener::StopTrack(TrackID aTrackID)
{
MOZ_ASSERT(NS_IsMainThread());
- if (((aTrackID == kAudioTrack && mAudioDevice) ||
- (aTrackID == kVideoTrack && mVideoDevice)) && !mStopped)
+ MOZ_ASSERT(aTrackID == kAudioTrack || aTrackID == kVideoTrack);
+
+ // XXX to support multiple tracks of a type in a stream, this should key off
+ // the TrackID and not just hard coded values.
+
+ bool stopAudio = aTrackID == kAudioTrack;
+ bool stopVideo = aTrackID == kVideoTrack;
+
+ if (mStopped ||
+ (stopAudio && (mAudioStopped || !mAudioDevice)) ||
+ (stopVideo && (mVideoStopped || !mVideoDevice)))
{
- // XXX to support multiple tracks of a type in a stream, this should key off
- // the TrackID and not just hard coded values.
- bool stopAudio = aTrackID == kAudioTrack && !mAudioStopped;
- bool stopVideo = aTrackID == kVideoTrack && !mVideoStopped;
- MediaManager::PostTask(FROM_HERE,
- new MediaOperationTask(MEDIA_STOP_TRACK,
- this, nullptr, nullptr,
- stopAudio ? mAudioDevice.get() : nullptr,
- stopVideo ? mVideoDevice.get() : nullptr,
- mFinished, mWindowID, nullptr));
- mAudioStopped |= stopAudio;
- mVideoStopped |= stopVideo;
- } else {
- LOG(("gUM track %d ended, but we don't have type %s",
- aTrackID, aTrackID == kAudioTrack ? "audio" : "video"));
+ LOG(("Can't stop gUM track %d (%s), exists=%d, stopped=%d",
+ aTrackID,
+ aTrackID == kAudioTrack ? "audio" : "video",
+ aTrackID == kAudioTrack ? !!mAudioDevice : !!mVideoDevice,
+ aTrackID == kAudioTrack ? mAudioStopped : mVideoStopped));
+ return;
}
+
+ if ((stopAudio || mAudioStopped || !mAudioDevice) &&
+ (stopVideo || mVideoStopped || !mVideoDevice)) {
+ Stop();
+ return;
+ }
+
+ MediaManager::PostTask(FROM_HERE,
+ new MediaOperationTask(MEDIA_STOP_TRACK,
+ this, nullptr, nullptr,
+ stopAudio ? mAudioDevice.get() : nullptr,
+ stopVideo ? mVideoDevice.get() : nullptr,
+ false , mWindowID, nullptr));
+ mAudioStopped |= stopAudio;
+ mVideoStopped |= stopVideo;
}
void
GetUserMediaCallbackMediaStreamListener::NotifyFinished()
{
MOZ_ASSERT(NS_IsMainThread());
mFinished = true;
- Invalidate(); // we know it's been activated
+ Stop(); // we know it's been activated
RefPtr<MediaManager> manager(MediaManager::GetInstance());
manager->RemoveFromWindowList(mWindowID, this);
}
// Called from the MediaStreamGraph thread
void
GetUserMediaCallbackMediaStreamListener::NotifyDirectListeners(MediaStreamGraph* aGraph,
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -220,17 +220,17 @@ public:
MOZ_ASSERT(NS_IsMainThread());
return mVideoDevice && !mStopped &&
mVideoDevice->GetSource()->IsAvailable() &&
mVideoDevice->GetMediaSource() == dom::MediaSourceEnum::Browser;
}
// implement in .cpp to avoid circular dependency with MediaOperationTask
// Can be invoked from EITHER MainThread or MSG thread
- void Invalidate();
+ void Stop();
void
AudioConfig(bool aEchoOn, uint32_t aEcho,
bool aAgcOn, uint32_t aAGC,
bool aNoiseOn, uint32_t aNoise,
int32_t aPlayoutDelay);
void
@@ -313,17 +313,17 @@ private:
// true after this listener has been removed from its MediaStream.
// MainThread only.
bool mRemoved;
// true if we have sent MEDIA_STOP or MEDIA_STOP_TRACK for mAudioDevice.
// MainThread only.
bool mAudioStopped;
- // true if we have sent MEDIA_STOP or MEDIA_STOP_TRACK for mAudioDevice.
+ // true if we have sent MEDIA_STOP or MEDIA_STOP_TRACK for mVideoDevice.
// MainThread only.
bool mVideoStopped;
// Set at Activate on MainThread
// Accessed from MediaStreamGraph thread, MediaManager thread, and MainThread
// No locking needed as they're only addrefed except on the MediaManager thread
RefPtr<AudioDevice> mAudioDevice; // threadsafe refcnt