OLD | NEW |
---|---|
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 "content/public/browser/browser_thread.h" | 7 #include "base/lazy_instance.h" |
8 | 8 |
9 namespace content { | 9 namespace content { |
10 | 10 |
11 namespace { | 11 namespace { |
12 | 12 |
13 // Debug utility to make sure methods of AudioMirroringManager are not invoked | 13 base::LazyInstance<AudioMirroringManager>::Leaky g_audio_mirroring_manager = |
14 // more than once in a single call stack. In release builds, this compiles to | 14 LAZY_INSTANCE_INITIALIZER; |
15 // nothing and gets completely optimized out. | |
16 class ReentrancyGuard { | |
miu
2014/08/27 19:54:58
I removed this since: 1) It's never triggered, and
| |
17 public: | |
18 #ifdef NDEBUG | |
19 ReentrancyGuard() {} | |
20 ~ReentrancyGuard() {} | |
21 #else | |
22 ReentrancyGuard() { | |
23 DCHECK(!inside_a_method_); | |
24 inside_a_method_ = true; | |
25 } | |
26 ~ReentrancyGuard() { | |
27 inside_a_method_ = false; | |
28 } | |
29 | |
30 static bool inside_a_method_; // Safe to be static, since AMM is a singleton. | |
31 #endif | |
32 }; | |
33 | |
34 #ifndef NDEBUG | |
35 bool ReentrancyGuard::inside_a_method_ = false; | |
36 #endif | |
37 | 15 |
38 } // namespace | 16 } // namespace |
39 | 17 |
40 AudioMirroringManager::AudioMirroringManager() {} | 18 // static |
19 AudioMirroringManager* AudioMirroringManager::GetInstance() { | |
20 return g_audio_mirroring_manager.Pointer(); | |
21 } | |
41 | 22 |
42 AudioMirroringManager::~AudioMirroringManager() { | 23 AudioMirroringManager::AudioMirroringManager() { |
43 DCHECK(diverters_.empty()); | 24 // Only *after* construction, check that AudioMirroringManager is being |
44 DCHECK(sessions_.empty()); | 25 // invoked on the same single thread. |
26 thread_checker_.DetachFromThread(); | |
45 } | 27 } |
46 | 28 |
29 AudioMirroringManager::~AudioMirroringManager() {} | |
30 | |
47 void AudioMirroringManager::AddDiverter( | 31 void AudioMirroringManager::AddDiverter( |
48 int render_process_id, int render_view_id, Diverter* diverter) { | 32 int render_process_id, int render_view_id, Diverter* diverter) { |
49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 33 DCHECK(thread_checker_.CalledOnValidThread()); |
50 ReentrancyGuard guard; | |
51 DCHECK(diverter); | 34 DCHECK(diverter); |
52 | 35 |
53 // DCHECK(diverter not already in diverters_ under any key) | 36 // DCHECK(diverter not already in diverters_ under any key) |
54 #ifndef NDEBUG | 37 #ifndef NDEBUG |
55 for (DiverterMap::const_iterator it = diverters_.begin(); | 38 for (DiverterMap::const_iterator it = diverters_.begin(); |
56 it != diverters_.end(); ++it) { | 39 it != diverters_.end(); ++it) { |
57 DCHECK_NE(diverter, it->second); | 40 DCHECK_NE(diverter, it->second); |
58 } | 41 } |
59 #endif | 42 #endif |
60 | 43 |
61 // Add the diverter to the set of active diverters. | 44 // Add the diverter to the set of active diverters. |
62 const Target target(render_process_id, render_view_id); | 45 const Target target(render_process_id, render_view_id); |
63 diverters_.insert(std::make_pair(target, diverter)); | 46 diverters_.insert(std::make_pair(target, diverter)); |
64 | 47 |
65 // If a mirroring session is active, start diverting the audio stream | 48 // If a mirroring session is active, start diverting the audio stream |
66 // immediately. | 49 // immediately. |
67 SessionMap::iterator session_it = sessions_.find(target); | 50 SessionMap::iterator session_it = sessions_.find(target); |
68 if (session_it != sessions_.end()) { | 51 if (session_it != sessions_.end()) { |
69 diverter->StartDiverting( | 52 diverter->StartDiverting( |
70 session_it->second->AddInput(diverter->GetAudioParameters())); | 53 session_it->second->AddInput(diverter->GetAudioParameters())); |
71 } | 54 } |
72 } | 55 } |
73 | 56 |
74 void AudioMirroringManager::RemoveDiverter( | 57 void AudioMirroringManager::RemoveDiverter( |
75 int render_process_id, int render_view_id, Diverter* diverter) { | 58 int render_process_id, int render_view_id, Diverter* diverter) { |
76 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 59 DCHECK(thread_checker_.CalledOnValidThread()); |
77 ReentrancyGuard guard; | |
78 | 60 |
79 // Stop diverting the audio stream if a mirroring session is active. | 61 // Stop diverting the audio stream if a mirroring session is active. |
80 const Target target(render_process_id, render_view_id); | 62 const Target target(render_process_id, render_view_id); |
81 SessionMap::iterator session_it = sessions_.find(target); | 63 SessionMap::iterator session_it = sessions_.find(target); |
82 if (session_it != sessions_.end()) | 64 if (session_it != sessions_.end()) |
83 diverter->StopDiverting(); | 65 diverter->StopDiverting(); |
84 | 66 |
85 // Remove the diverter from the set of active diverters. | 67 // Remove the diverter from the set of active diverters. |
86 for (DiverterMap::iterator it = diverters_.lower_bound(target); | 68 for (DiverterMap::iterator it = diverters_.lower_bound(target); |
87 it != diverters_.end() && it->first == target; ++it) { | 69 it != diverters_.end() && it->first == target; ++it) { |
88 if (it->second == diverter) { | 70 if (it->second == diverter) { |
89 diverters_.erase(it); | 71 diverters_.erase(it); |
90 break; | 72 break; |
91 } | 73 } |
92 } | 74 } |
93 } | 75 } |
94 | 76 |
95 void AudioMirroringManager::StartMirroring( | 77 void AudioMirroringManager::StartMirroring( |
96 int render_process_id, int render_view_id, | 78 int render_process_id, int render_view_id, |
97 MirroringDestination* destination) { | 79 MirroringDestination* destination) { |
98 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 80 DCHECK(thread_checker_.CalledOnValidThread()); |
99 ReentrancyGuard guard; | |
100 DCHECK(destination); | 81 DCHECK(destination); |
101 | 82 |
102 // Insert an entry into the set of active mirroring sessions. If a mirroring | 83 // Insert an entry into the set of active mirroring sessions. If a mirroring |
103 // session is already active for |render_process_id| + |render_view_id|, | 84 // session is already active for |render_process_id| + |render_view_id|, |
104 // replace the entry. | 85 // replace the entry. |
105 const Target target(render_process_id, render_view_id); | 86 const Target target(render_process_id, render_view_id); |
106 SessionMap::iterator session_it = sessions_.find(target); | 87 SessionMap::iterator session_it = sessions_.find(target); |
107 MirroringDestination* old_destination; | 88 MirroringDestination* old_destination; |
108 if (session_it == sessions_.end()) { | 89 if (session_it == sessions_.end()) { |
109 old_destination = NULL; | 90 old_destination = NULL; |
(...skipping 20 matching lines...) Expand all Loading... | |
130 if (old_destination) | 111 if (old_destination) |
131 diverter->StopDiverting(); | 112 diverter->StopDiverting(); |
132 diverter->StartDiverting( | 113 diverter->StartDiverting( |
133 destination->AddInput(diverter->GetAudioParameters())); | 114 destination->AddInput(diverter->GetAudioParameters())); |
134 } | 115 } |
135 } | 116 } |
136 | 117 |
137 void AudioMirroringManager::StopMirroring( | 118 void AudioMirroringManager::StopMirroring( |
138 int render_process_id, int render_view_id, | 119 int render_process_id, int render_view_id, |
139 MirroringDestination* destination) { | 120 MirroringDestination* destination) { |
140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 121 DCHECK(thread_checker_.CalledOnValidThread()); |
141 ReentrancyGuard guard; | |
142 | 122 |
143 // Stop mirroring if there is an active session *and* the destination | 123 // Stop mirroring if there is an active session *and* the destination |
144 // matches. | 124 // matches. |
145 const Target target(render_process_id, render_view_id); | 125 const Target target(render_process_id, render_view_id); |
146 SessionMap::iterator session_it = sessions_.find(target); | 126 SessionMap::iterator session_it = sessions_.find(target); |
147 if (session_it == sessions_.end() || destination != session_it->second) | 127 if (session_it == sessions_.end() || destination != session_it->second) |
148 return; | 128 return; |
149 | 129 |
150 DVLOG(1) << "Stop mirroring render_process_id:render_view_id=" | 130 DVLOG(1) << "Stop mirroring render_process_id:render_view_id=" |
151 << render_process_id << ':' << render_view_id | 131 << render_process_id << ':' << render_view_id |
152 << " --> MirroringDestination@" << destination; | 132 << " --> MirroringDestination@" << destination; |
153 | 133 |
154 // Stop diverting each audio stream in the mirroring session being stopped. | 134 // Stop diverting each audio stream in the mirroring session being stopped. |
155 for (DiverterMap::iterator it = diverters_.lower_bound(target); | 135 for (DiverterMap::iterator it = diverters_.lower_bound(target); |
156 it != diverters_.end() && it->first == target; ++it) { | 136 it != diverters_.end() && it->first == target; ++it) { |
157 it->second->StopDiverting(); | 137 it->second->StopDiverting(); |
158 } | 138 } |
159 | 139 |
160 // Remove the entry from the set of active mirroring sessions. | 140 // Remove the entry from the set of active mirroring sessions. |
161 sessions_.erase(session_it); | 141 sessions_.erase(session_it); |
162 } | 142 } |
163 | 143 |
164 } // namespace content | 144 } // namespace content |
OLD | NEW |