Index: content/browser/media/capture/audio_mirroring_manager.cc |
diff --git a/content/browser/media/capture/audio_mirroring_manager.cc b/content/browser/media/capture/audio_mirroring_manager.cc |
index f8b8b3a5b183e9d1b1ff07dd6728279b368d0c88..5de94815e15ce6718f33a1d5423033a6f1edc8e5 100644 |
--- a/content/browser/media/capture/audio_mirroring_manager.cc |
+++ b/content/browser/media/capture/audio_mirroring_manager.cc |
@@ -62,7 +62,13 @@ void AudioMirroringManager::RemoveDiverter(Diverter* diverter) { |
// diverted, it is stopped. |
for (StreamRoutes::iterator it = routes_.begin(); it != routes_.end(); ++it) { |
if (it->diverter == diverter) { |
- ChangeRoute(&(*it), NULL); |
+ // Stop the diverted flow. |
+ RouteDivertedFlow(&(*it), NULL); |
+ |
+ // Stop duplication flows. |
+ for (auto& dup : it->duplications) { |
+ diverter->StopDuplicating(dup.second); |
+ } |
routes_.erase(it); |
return; |
} |
@@ -81,12 +87,12 @@ void AudioMirroringManager::StartMirroring(MirroringDestination* destination) { |
sessions_.push_back(destination); |
} |
+ std::set<SourceFrameRef> candidates; |
+ |
// Query the MirroringDestination to see which of the audio streams should be |
// diverted. |
- std::set<SourceFrameRef> candidates; |
for (StreamRoutes::const_iterator it = routes_.begin(); it != routes_.end(); |
++it) { |
- if (!it->destination || it->destination == destination) |
candidates.insert(it->source_render_frame); |
} |
if (!candidates.empty()) { |
@@ -108,9 +114,14 @@ void AudioMirroringManager::StopMirroring(MirroringDestination* destination) { |
std::set<SourceFrameRef> redivert_candidates; |
for (StreamRoutes::iterator it = routes_.begin(); it != routes_.end(); ++it) { |
if (it->destination == destination) { |
- ChangeRoute(&(*it), NULL); |
+ RouteDivertedFlow(&(*it), NULL); |
redivert_candidates.insert(it->source_render_frame); |
} |
+ auto dup_it = it->duplications.find(destination); |
+ if (dup_it != it->duplications.end()) { |
+ it->diverter->StopDuplicating(dup_it->second); |
+ it->duplications.erase(dup_it); |
+ } |
} |
if (!redivert_candidates.empty()) |
InitiateQueriesToFindNewDestination(destination, redivert_candidates); |
@@ -132,20 +143,30 @@ void AudioMirroringManager::InitiateQueriesToFindNewDestination( |
for (Destinations::const_iterator it = sessions_.begin(); |
it != sessions_.end(); ++it) { |
- if (*it != old_destination) { |
- (*it)->QueryForMatches( |
- candidates, |
- base::Bind(&AudioMirroringManager::UpdateRoutesToDestination, |
- base::Unretained(this), |
- *it, |
- true)); |
- } |
+ if (*it == old_destination) |
+ continue; |
+ |
+ (*it)->QueryForMatches( |
+ candidates, |
+ base::Bind(&AudioMirroringManager::UpdateRoutesToDestination, |
+ base::Unretained(this), *it, true)); |
} |
} |
void AudioMirroringManager::UpdateRoutesToDestination( |
MirroringDestination* destination, |
bool add_only, |
+ const std::set<SourceFrameRef>& matches, |
+ bool is_duplicate) { |
+ if (is_duplicate) |
+ UpdateRoutesToDuplicateDestination(destination, add_only, matches); |
+ else |
+ UpdateRoutesToDivertDestination(destination, add_only, matches); |
+} |
+ |
+void AudioMirroringManager::UpdateRoutesToDivertDestination( |
+ MirroringDestination* destination, |
+ bool add_only, |
const std::set<SourceFrameRef>& matches) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
@@ -164,11 +185,11 @@ void AudioMirroringManager::UpdateRoutesToDestination( |
if (matches.find(it->source_render_frame) != matches.end()) { |
// Only change the route if the stream is not already being diverted. |
if (!it->destination) |
- ChangeRoute(&(*it), destination); |
+ RouteDivertedFlow(&(*it), destination); |
} else if (!add_only) { |
// Only stop diverting if the stream is currently routed to |destination|. |
if (it->destination == destination) { |
- ChangeRoute(&(*it), NULL); |
+ RouteDivertedFlow(&(*it), NULL); |
redivert_candidates.insert(it->source_render_frame); |
} |
} |
@@ -177,9 +198,47 @@ void AudioMirroringManager::UpdateRoutesToDestination( |
InitiateQueriesToFindNewDestination(destination, redivert_candidates); |
} |
+void AudioMirroringManager::UpdateRoutesToDuplicateDestination( |
+ MirroringDestination* destination, |
+ bool add_only, |
+ const std::set<SourceFrameRef>& matches) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ if (std::find(sessions_.begin(), sessions_.end(), destination) == |
+ sessions_.end()) { |
+ return; // Query result callback invoked after StopMirroring(). |
+ } |
+ |
+ for (StreamRoutes::iterator it = routes_.begin(); it != routes_.end(); ++it) { |
+ if (matches.find(it->source_render_frame) != matches.end()) { |
+ // The same destination cannot have both a diverted audio flow and a |
+ // duplicated flow from the same source. |
+ DCHECK_NE(it->destination, destination); |
+ |
+ media::AudioPushSink*& pusher = it->duplications[destination]; |
+ if (!pusher) { |
+ pusher = destination->AddPushInput(it->diverter->GetAudioParameters()); |
+ DCHECK(pusher); |
+ it->diverter->StartDuplicating(pusher); |
+ } |
+ } else if (!add_only) { |
+ auto dup_it = it->duplications.find(destination); |
+ if (dup_it != it->duplications.end()) { |
+ it->diverter->StopDuplicating(dup_it->second); |
+ it->duplications.erase(dup_it); |
+ } |
+ } |
+ } |
+} |
+ |
// static |
-void AudioMirroringManager::ChangeRoute( |
- StreamRoutingState* route, MirroringDestination* new_destination) { |
+void AudioMirroringManager::RouteDivertedFlow( |
+ StreamRoutingState* route, |
+ MirroringDestination* new_destination) { |
+ // The same destination cannot have both a diverted audio flow and a |
+ // duplicated flow from the same source. |
+ DCHECK(route->duplications.find(new_destination) == |
+ route->duplications.end()); |
+ |
if (route->destination == new_destination) |
return; // No change. |