Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(856)

Side by Side Diff: content/browser/media/capture/audio_mirroring_manager.cc

Issue 542863004: Site Isolation: RenderView-->RenderFrame for WebContentsVideoCaptureDevice and WebContentsAudioInpu… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/media/capture/audio_mirroring_manager.h" 5 #include "content/browser/media/capture/audio_mirroring_manager.h"
6 6
7 #include <algorithm>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
7 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
8 12
9 namespace content { 13 namespace content {
10 14
11 namespace { 15 namespace {
12 16
13 base::LazyInstance<AudioMirroringManager>::Leaky g_audio_mirroring_manager = 17 base::LazyInstance<AudioMirroringManager>::Leaky g_audio_mirroring_manager =
14 LAZY_INSTANCE_INITIALIZER; 18 LAZY_INSTANCE_INITIALIZER;
15 19
16 } // namespace 20 } // namespace
17 21
18 // static 22 // static
19 AudioMirroringManager* AudioMirroringManager::GetInstance() { 23 AudioMirroringManager* AudioMirroringManager::GetInstance() {
20 return g_audio_mirroring_manager.Pointer(); 24 return g_audio_mirroring_manager.Pointer();
21 } 25 }
22 26
23 AudioMirroringManager::AudioMirroringManager() { 27 AudioMirroringManager::AudioMirroringManager() {
24 // Only *after* construction, check that AudioMirroringManager is being 28 // Only *after* construction, check that AudioMirroringManager is being
25 // invoked on the same single thread. 29 // invoked on the same single thread.
26 thread_checker_.DetachFromThread(); 30 thread_checker_.DetachFromThread();
27 } 31 }
28 32
29 AudioMirroringManager::~AudioMirroringManager() {} 33 AudioMirroringManager::~AudioMirroringManager() {}
30 34
31 void AudioMirroringManager::AddDiverter( 35 void AudioMirroringManager::AddDiverter(
32 int render_process_id, int render_view_id, Diverter* diverter) { 36 int render_process_id, int render_frame_id, Diverter* diverter) {
33 DCHECK(thread_checker_.CalledOnValidThread()); 37 DCHECK(thread_checker_.CalledOnValidThread());
34 DCHECK(diverter); 38 DCHECK(diverter);
35 39
36 // DCHECK(diverter not already in diverters_ under any key) 40 // DCHECK(diverter not already in routes_)
37 #ifndef NDEBUG 41 #ifndef NDEBUG
38 for (DiverterMap::const_iterator it = diverters_.begin(); 42 for (StreamRoutes::const_iterator it = routes_.begin();
39 it != diverters_.end(); ++it) { 43 it != routes_.end(); ++it) {
40 DCHECK_NE(diverter, it->second); 44 DCHECK_NE(diverter, it->diverter);
41 } 45 }
42 #endif 46 #endif
47 routes_.push_back(StreamRoutingState(
48 SourceFrameRef(render_process_id, render_frame_id),
49 diverter));
43 50
44 // Add the diverter to the set of active diverters. 51 // Query existing destinations to see whether to immediately start diverting
45 const Target target(render_process_id, render_view_id); 52 // the stream.
46 diverters_.insert(std::make_pair(target, diverter)); 53 std::set<SourceFrameRef> candidates;
54 candidates.insert(routes_.back().source_render_frame);
55 AttemptNewMatches(NULL, candidates);
56 }
47 57
48 // If a mirroring session is active, start diverting the audio stream 58 void AudioMirroringManager::RemoveDiverter(Diverter* diverter) {
49 // immediately. 59 DCHECK(thread_checker_.CalledOnValidThread());
50 SessionMap::iterator session_it = sessions_.find(target); 60
51 if (session_it != sessions_.end()) { 61 // Find and remove the entry from the routing table. If the stream is being
52 diverter->StartDiverting( 62 // diverted, it is stopped.
53 session_it->second->AddInput(diverter->GetAudioParameters())); 63 for (StreamRoutes::iterator it = routes_.begin(); it != routes_.end(); ++it) {
64 if (it->diverter == diverter) {
65 ChangeRoute(&(*it), NULL);
66 routes_.erase(it);
67 return;
68 }
69 }
70 NOTREACHED();
71 }
72
73 void AudioMirroringManager::StartMirroring(MirroringDestination* destination) {
74 DCHECK(thread_checker_.CalledOnValidThread());
75 DCHECK(destination);
76
77 // Insert an entry into the set of active mirroring sessions, if this is a
78 // previously-unknown destination.
79 if (std::find(sessions_.begin(), sessions_.end(), destination) ==
80 sessions_.end()) {
81 sessions_.push_back(destination);
82 }
83
84 // Query the MirroringDestination to see which of the audio streams should be
85 // diverted.
86 std::set<SourceFrameRef> candidates;
87 for (StreamRoutes::const_iterator it = routes_.begin(); it != routes_.end();
88 ++it) {
89 if (!it->destination || it->destination == destination)
90 candidates.insert(it->source_render_frame);
91 }
92 if (!candidates.empty()) {
93 destination->QueryForMatches(
94 candidates,
95 base::Bind(&AudioMirroringManager::UpdateRoutesToDestination,
96 base::Unretained(this),
97 destination,
98 false));
54 } 99 }
55 } 100 }
56 101
57 void AudioMirroringManager::RemoveDiverter( 102 void AudioMirroringManager::StopMirroring(MirroringDestination* destination) {
58 int render_process_id, int render_view_id, Diverter* diverter) {
59 DCHECK(thread_checker_.CalledOnValidThread()); 103 DCHECK(thread_checker_.CalledOnValidThread());
60 104
61 // Stop diverting the audio stream if a mirroring session is active. 105 // Stop diverting each audio stream in the mirroring session being stopped.
62 const Target target(render_process_id, render_view_id); 106 // Each stopped stream becomes a candidate to be diverted to another
63 SessionMap::iterator session_it = sessions_.find(target); 107 // destination.
64 if (session_it != sessions_.end()) 108 std::set<SourceFrameRef> redivert_candidates;
65 diverter->StopDiverting(); 109 for (StreamRoutes::iterator it = routes_.begin(); it != routes_.end(); ++it) {
110 if (it->destination == destination) {
111 ChangeRoute(&(*it), NULL);
112 redivert_candidates.insert(it->source_render_frame);
113 }
114 }
115 if (!redivert_candidates.empty())
116 AttemptNewMatches(destination, redivert_candidates);
66 117
67 // Remove the diverter from the set of active diverters. 118 // Remove the entry from the set of active mirroring sessions.
68 for (DiverterMap::iterator it = diverters_.lower_bound(target); 119 const Destinations::iterator dest_it =
69 it != diverters_.end() && it->first == target; ++it) { 120 std::find(sessions_.begin(), sessions_.end(), destination);
70 if (it->second == diverter) { 121 if (dest_it == sessions_.end()) {
71 diverters_.erase(it); 122 NOTREACHED();
72 break; 123 return;
124 }
125 sessions_.erase(dest_it);
126 }
127
128 void AudioMirroringManager::AttemptNewMatches(
129 MirroringDestination* old_destination,
130 const std::set<SourceFrameRef>& candidates) {
131 DCHECK(thread_checker_.CalledOnValidThread());
132
133 for (Destinations::const_iterator it = sessions_.begin();
134 it != sessions_.end(); ++it) {
135 if (*it != old_destination) {
136 (*it)->QueryForMatches(
137 candidates,
138 base::Bind(&AudioMirroringManager::UpdateRoutesToDestination,
139 base::Unretained(this),
140 *it,
141 true));
73 } 142 }
74 } 143 }
75 } 144 }
76 145
77 void AudioMirroringManager::StartMirroring( 146 void AudioMirroringManager::UpdateRoutesToDestination(
78 int render_process_id, int render_view_id, 147 MirroringDestination* destination,
79 MirroringDestination* destination) { 148 bool add_only,
149 const std::set<SourceFrameRef>& matches) {
80 DCHECK(thread_checker_.CalledOnValidThread()); 150 DCHECK(thread_checker_.CalledOnValidThread());
81 DCHECK(destination);
82 151
83 // Insert an entry into the set of active mirroring sessions. If a mirroring 152 if (std::find(sessions_.begin(), sessions_.end(), destination) ==
84 // session is already active for |render_process_id| + |render_view_id|, 153 sessions_.end()) {
85 // replace the entry. 154 return; // Query result callback invoked after StopMirroring().
86 const Target target(render_process_id, render_view_id);
87 SessionMap::iterator session_it = sessions_.find(target);
88 MirroringDestination* old_destination;
89 if (session_it == sessions_.end()) {
90 old_destination = NULL;
91 sessions_.insert(std::make_pair(target, destination));
92
93 DVLOG(1) << "Start mirroring render_process_id:render_view_id="
94 << render_process_id << ':' << render_view_id
95 << " --> MirroringDestination@" << destination;
96 } else {
97 old_destination = session_it->second;
98 session_it->second = destination;
99
100 DVLOG(1) << "Switch mirroring of render_process_id:render_view_id="
101 << render_process_id << ':' << render_view_id
102 << " MirroringDestination@" << old_destination
103 << " --> MirroringDestination@" << destination;
104 } 155 }
105 156
106 // Divert audio streams coming from |target| to |destination|. If streams 157 DVLOG(1) << (add_only ? "Add " : "Replace with ") << matches.size()
107 // were already diverted to the |old_destination|, remove them. 158 << " routes to MirroringDestination@" << destination;
108 for (DiverterMap::iterator it = diverters_.lower_bound(target); 159
109 it != diverters_.end() && it->first == target; ++it) { 160 // Start/stop diverting based on |matches|. Any stopped stream becomes a
110 Diverter* const diverter = it->second; 161 // candidate to be diverted to another destination.
DaleCurtis 2014/09/05 22:41:41 It seems that the list of candidates can change be
miu 2014/09/08 22:50:54 I do these in the loop. Line 166 checks that the
111 if (old_destination) 162 std::set<SourceFrameRef> redivert_candidates;
112 diverter->StopDiverting(); 163 for (StreamRoutes::iterator it = routes_.begin(); it != routes_.end(); ++it) {
113 diverter->StartDiverting( 164 if (matches.find(it->source_render_frame) != matches.end()) {
114 destination->AddInput(diverter->GetAudioParameters())); 165 // Only change the route if the stream is not already being diverted.
166 if (!it->destination)
167 ChangeRoute(&(*it), destination);
168 } else if (!add_only) {
169 // Only stop diverting if the stream is currently routed to |destination|.
170 if (it->destination == destination) {
171 ChangeRoute(&(*it), NULL);
172 redivert_candidates.insert(it->source_render_frame);
173 }
174 }
175 }
176 if (!redivert_candidates.empty())
177 AttemptNewMatches(destination, redivert_candidates);
178 }
179
180 // static
181 void AudioMirroringManager::ChangeRoute(
182 StreamRoutingState* route, MirroringDestination* new_destination) {
183 if (route->destination == new_destination)
184 return; // No change.
185
186 if (route->destination) {
187 DVLOG(1) << "Stop diverting render_process_id:render_frame_id="
188 << route->source_render_frame.first << ':'
189 << route->source_render_frame.second
190 << " --> MirroringDestination@" << route->destination;
191 route->diverter->StopDiverting();
192 route->destination = NULL;
193 }
194
195 if (new_destination) {
196 DVLOG(1) << "Start diverting of render_process_id:render_frame_id="
197 << route->source_render_frame.first << ':'
198 << route->source_render_frame.second
199 << " --> MirroringDestination@" << new_destination;
200 route->diverter->StartDiverting(
201 new_destination->AddInput(route->diverter->GetAudioParameters()));
202 route->destination = new_destination;
115 } 203 }
116 } 204 }
117 205
118 void AudioMirroringManager::StopMirroring( 206 AudioMirroringManager::StreamRoutingState::StreamRoutingState(
119 int render_process_id, int render_view_id, 207 const SourceFrameRef& source_frame, Diverter* stream_diverter)
120 MirroringDestination* destination) { 208 : source_render_frame(source_frame),
121 DCHECK(thread_checker_.CalledOnValidThread()); 209 diverter(stream_diverter),
210 destination(NULL) {}
122 211
123 // Stop mirroring if there is an active session *and* the destination 212 AudioMirroringManager::StreamRoutingState::~StreamRoutingState() {}
124 // matches.
125 const Target target(render_process_id, render_view_id);
126 SessionMap::iterator session_it = sessions_.find(target);
127 if (session_it == sessions_.end() || destination != session_it->second)
128 return;
129
130 DVLOG(1) << "Stop mirroring render_process_id:render_view_id="
131 << render_process_id << ':' << render_view_id
132 << " --> MirroringDestination@" << destination;
133
134 // Stop diverting each audio stream in the mirroring session being stopped.
135 for (DiverterMap::iterator it = diverters_.lower_bound(target);
136 it != diverters_.end() && it->first == target; ++it) {
137 it->second->StopDiverting();
138 }
139
140 // Remove the entry from the set of active mirroring sessions.
141 sessions_.erase(session_it);
142 }
143 213
144 } // namespace content 214 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698