| 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.
|
|
|
|
|