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

Side by Side Diff: content/renderer/media/webrtc_local_audio_track.cc

Issue 1721273002: MediaStream audio object graph untangling and clean-ups. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed mcasas's 1st round comments, plus REBASE. Created 4 years, 10 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/renderer/media/webrtc_local_audio_track.h" 5 #include "content/renderer/media/webrtc_local_audio_track.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <limits> 9 #include <limits>
10 10
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
11 #include "content/public/renderer/media_stream_audio_sink.h" 13 #include "content/public/renderer/media_stream_audio_sink.h"
12 #include "content/renderer/media/media_stream_audio_level_calculator.h"
13 #include "content/renderer/media/media_stream_audio_processor.h" 14 #include "content/renderer/media/media_stream_audio_processor.h"
14 #include "content/renderer/media/media_stream_audio_sink_owner.h" 15 #include "content/renderer/media/media_stream_audio_sink_owner.h"
15 #include "content/renderer/media/media_stream_audio_track_sink.h" 16 #include "content/renderer/media/media_stream_audio_track_sink.h"
16 #include "content/renderer/media/webaudio_capturer_source.h"
17 #include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h" 17 #include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
18 #include "content/renderer/media/webrtc_audio_capturer.h"
19 18
20 namespace content { 19 namespace content {
21 20
22 WebRtcLocalAudioTrack::WebRtcLocalAudioTrack( 21 WebRtcLocalAudioTrack::WebRtcLocalAudioTrack(
23 WebRtcLocalAudioTrackAdapter* adapter, 22 scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter)
24 const scoped_refptr<WebRtcAudioCapturer>& capturer, 23 : MediaStreamAudioTrack(true), adapter_(adapter) {
25 WebAudioCapturerSource* webaudio_source)
26 : MediaStreamAudioTrack(true),
27 adapter_(adapter),
28 capturer_(capturer),
29 webaudio_source_(webaudio_source) {
30 DCHECK(capturer.get() || webaudio_source);
31 signal_thread_checker_.DetachFromThread(); 24 signal_thread_checker_.DetachFromThread();
25 DVLOG(1) << "WebRtcLocalAudioTrack::WebRtcLocalAudioTrack()";
26
27 MediaStreamAudioTrack::AddStopObserver(base::Bind(
28 &WebRtcLocalAudioTrack::RemoveAllSinks, base::Unretained(this)));
o1ka 2016/02/29 14:28:05 See the comment to MediaStreamAudioTrack destructo
miu 2016/03/01 09:43:55 Done.
o1ka 2016/03/01 14:18:59 Acknowledged.
32 29
33 adapter_->Initialize(this); 30 adapter_->Initialize(this);
34
35 DVLOG(1) << "WebRtcLocalAudioTrack::WebRtcLocalAudioTrack()";
36 } 31 }
37 32
38 WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() { 33 WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() {
39 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 34 DCHECK(main_render_thread_checker_.CalledOnValidThread());
40 DVLOG(1) << "WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack()"; 35 DVLOG(1) << "WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack()";
41 // Users might not call Stop() on the track. 36
37 // Even though the base class calls Stop(), do it here because the stop
38 // callback added in this class's constructor needs to be run before the data
39 // members of this class are destroyed.
42 Stop(); 40 Stop();
o1ka 2016/02/29 14:28:05 That's why this pattern with stop observers and ca
miu 2016/03/01 09:43:55 Done.
o1ka 2016/03/01 14:18:59 Acknowledged.
43 } 41 }
44 42
45 media::AudioParameters WebRtcLocalAudioTrack::GetOutputFormat() const { 43 media::AudioParameters WebRtcLocalAudioTrack::GetOutputFormat() const {
46 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 44 DCHECK(main_render_thread_checker_.CalledOnValidThread());
47 if (webaudio_source_.get()) { 45 base::AutoLock auto_lock(lock_);
48 return media::AudioParameters(); 46 return audio_parameters_;
49 } else {
50 return capturer_->GetOutputFormat();
51 }
52 } 47 }
53 48
54 void WebRtcLocalAudioTrack::Capture(const media::AudioBus& audio_bus, 49 void WebRtcLocalAudioTrack::Capture(const media::AudioBus& audio_bus,
55 base::TimeTicks estimated_capture_time, 50 base::TimeTicks estimated_capture_time) {
56 bool force_report_nonzero_energy) {
57 DCHECK(capture_thread_checker_.CalledOnValidThread()); 51 DCHECK(capture_thread_checker_.CalledOnValidThread());
58 DCHECK(!estimated_capture_time.is_null()); 52 DCHECK(!estimated_capture_time.is_null());
59 53
60 // Calculate the signal level regardless of whether the track is disabled or
61 // enabled. If |force_report_nonzero_energy| is true, |audio_bus| contains
62 // post-processed data that may be all zeros even though the signal contained
63 // energy before the processing. In this case, report nonzero energy even if
64 // the energy of the data in |audio_bus| is zero.
65 const float minimum_signal_level =
66 force_report_nonzero_energy ? 1.0f / std::numeric_limits<int16_t>::max()
67 : 0.0f;
68 const float signal_level = std::max(
69 minimum_signal_level,
70 std::min(1.0f, level_calculator_->Calculate(audio_bus)));
71 const int signal_level_as_pcm16 =
72 static_cast<int>(signal_level * std::numeric_limits<int16_t>::max() +
73 0.5f /* rounding to nearest int */);
74 adapter_->SetSignalLevel(signal_level_as_pcm16);
75
76 scoped_refptr<WebRtcAudioCapturer> capturer;
77 SinkList::ItemList sinks; 54 SinkList::ItemList sinks;
78 SinkList::ItemList sinks_to_notify_format; 55 SinkList::ItemList sinks_to_notify_format;
79 { 56 {
80 base::AutoLock auto_lock(lock_); 57 base::AutoLock auto_lock(lock_);
81 capturer = capturer_;
82 sinks = sinks_.Items(); 58 sinks = sinks_.Items();
83 sinks_.RetrieveAndClearTags(&sinks_to_notify_format); 59 sinks_.RetrieveAndClearTags(&sinks_to_notify_format);
84 } 60 }
85 61
86 // Notify the tracks on when the format changes. This will do nothing if 62 // Notify the tracks on when the format changes. This will do nothing if
87 // |sinks_to_notify_format| is empty. 63 // |sinks_to_notify_format| is empty. Note that accessing |audio_parameters_|
64 // without holding the |lock_| is valid since |audio_parameters_| is only
65 // changed on the current thread.
88 for (const auto& sink : sinks_to_notify_format) 66 for (const auto& sink : sinks_to_notify_format)
89 sink->OnSetFormat(audio_parameters_); 67 sink->OnSetFormat(audio_parameters_);
90 68
91 // Feed the data to the sinks. 69 // Feed the data to the sinks.
92 // TODO(jiayl): we should not pass the real audio data down if the track is 70 // TODO(jiayl): we should not pass the real audio data down if the track is
93 // disabled. This is currently done so to feed input to WebRTC typing 71 // disabled. This is currently done so to feed input to WebRTC typing
94 // detection and should be changed when audio processing is moved from 72 // detection and should be changed when audio processing is moved from
95 // WebRTC to the track. 73 // WebRTC to the track.
96 for (const auto& sink : sinks) 74 for (const auto& sink : sinks)
97 sink->OnData(audio_bus, estimated_capture_time); 75 sink->OnData(audio_bus, estimated_capture_time);
98 } 76 }
99 77
100 void WebRtcLocalAudioTrack::OnSetFormat( 78 void WebRtcLocalAudioTrack::OnSetFormat(
101 const media::AudioParameters& params) { 79 const media::AudioParameters& params) {
102 DVLOG(1) << "WebRtcLocalAudioTrack::OnSetFormat()"; 80 DVLOG(1) << "WebRtcLocalAudioTrack::OnSetFormat()";
103 // If the source is restarted, we might have changed to another capture 81 // If the source is restarted, we might have changed to another capture
104 // thread. 82 // thread.
105 capture_thread_checker_.DetachFromThread(); 83 capture_thread_checker_.DetachFromThread();
106 DCHECK(capture_thread_checker_.CalledOnValidThread()); 84 DCHECK(capture_thread_checker_.CalledOnValidThread());
107 85
86 base::AutoLock auto_lock(lock_);
108 audio_parameters_ = params; 87 audio_parameters_ = params;
109 level_calculator_.reset(new MediaStreamAudioLevelCalculator());
110
111 base::AutoLock auto_lock(lock_);
112 // Remember to notify all sinks of the new format. 88 // Remember to notify all sinks of the new format.
113 sinks_.TagAll(); 89 sinks_.TagAll();
114 } 90 }
115 91
116 void WebRtcLocalAudioTrack::SetAudioProcessor(
117 const scoped_refptr<MediaStreamAudioProcessor>& processor) {
118 // if the |processor| does not have audio processing, which can happen if
119 // kDisableAudioTrackProcessing is set set or all the constraints in
120 // the |processor| are turned off. In such case, we pass NULL to the
121 // adapter to indicate that no stats can be gotten from the processor.
122 adapter_->SetAudioProcessor(processor->has_audio_processing() ?
123 processor : NULL);
124 }
125
126 void WebRtcLocalAudioTrack::AddSink(MediaStreamAudioSink* sink) { 92 void WebRtcLocalAudioTrack::AddSink(MediaStreamAudioSink* sink) {
127 // This method is called from webrtc, on the signaling thread, when the local 93 // This method is called from webrtc, on the signaling thread, when the local
128 // description is set and from the main thread from WebMediaPlayerMS::load 94 // description is set and from the main thread from WebMediaPlayerMS::load
129 // (via WebRtcLocalAudioRenderer::Start). 95 // (via WebRtcLocalAudioRenderer::Start).
130 DCHECK(main_render_thread_checker_.CalledOnValidThread() || 96 DCHECK(main_render_thread_checker_.CalledOnValidThread() ||
131 signal_thread_checker_.CalledOnValidThread()); 97 signal_thread_checker_.CalledOnValidThread());
132 DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()"; 98 DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()";
133 base::AutoLock auto_lock(lock_); 99 base::AutoLock auto_lock(lock_);
134 100
135 // Verify that |sink| is not already added to the list. 101 // Verify that |sink| is not already added to the list.
(...skipping 23 matching lines...) Expand all
159 MediaStreamAudioTrackSink::WrapsMediaStreamSink(sink)); 125 MediaStreamAudioTrackSink::WrapsMediaStreamSink(sink));
160 } 126 }
161 127
162 // Clear the delegate to ensure that no more capture callbacks will 128 // Clear the delegate to ensure that no more capture callbacks will
163 // be sent to this sink. Also avoids a possible crash which can happen 129 // be sent to this sink. Also avoids a possible crash which can happen
164 // if this method is called while capturing is active. 130 // if this method is called while capturing is active.
165 if (removed_item.get()) 131 if (removed_item.get())
166 removed_item->Reset(); 132 removed_item->Reset();
167 } 133 }
168 134
169 void WebRtcLocalAudioTrack::Start() {
170 DCHECK(main_render_thread_checker_.CalledOnValidThread());
171 DVLOG(1) << "WebRtcLocalAudioTrack::Start()";
172 if (webaudio_source_.get()) {
173 // If the track is hooking up with WebAudio, do NOT add the track to the
174 // capturer as its sink otherwise two streams in different clock will be
175 // pushed through the same track.
176 webaudio_source_->Start(this);
177 } else if (capturer_.get()) {
178 capturer_->AddTrack(this);
179 }
180
181 SinkList::ItemList sinks;
182 {
183 base::AutoLock auto_lock(lock_);
184 sinks = sinks_.Items();
185 }
186 for (SinkList::ItemList::const_iterator it = sinks.begin();
187 it != sinks.end();
188 ++it) {
189 (*it)->OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateLive);
190 }
191 }
192
193 void WebRtcLocalAudioTrack::SetEnabled(bool enabled) { 135 void WebRtcLocalAudioTrack::SetEnabled(bool enabled) {
194 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 136 DCHECK(main_render_thread_checker_.CalledOnValidThread());
195 if (adapter_.get()) 137 if (adapter_.get())
196 adapter_->set_enabled(enabled); 138 adapter_->set_enabled(enabled);
197 } 139 }
198 140
199 void WebRtcLocalAudioTrack::Stop() { 141 void WebRtcLocalAudioTrack::RemoveAllSinks() {
200 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 142 DCHECK(main_render_thread_checker_.CalledOnValidThread());
201 DVLOG(1) << "WebRtcLocalAudioTrack::Stop()"; 143 DVLOG(1) << "WebRtcLocalAudioTrack::RemoveAllSinks()";
202 if (!capturer_.get() && !webaudio_source_.get())
203 return;
204 144
205 if (webaudio_source_.get()) { 145 // Protect the pointers using the lock when accessing |sinks_|.
206 // Called Stop() on the |webaudio_source_| explicitly so that
207 // |webaudio_source_| won't push more data to the track anymore.
208 // Also note that the track is not registered as a sink to the |capturer_|
209 // in such case and no need to call RemoveTrack().
210 webaudio_source_->Stop();
211 } else {
212 // It is necessary to call RemoveTrack on the |capturer_| to avoid getting
213 // audio callback after Stop().
214 capturer_->RemoveTrack(this);
215 }
216
217 // Protect the pointers using the lock when accessing |sinks_| and
218 // setting the |capturer_| to NULL.
219 SinkList::ItemList sinks; 146 SinkList::ItemList sinks;
220 { 147 {
221 base::AutoLock auto_lock(lock_); 148 base::AutoLock auto_lock(lock_);
222 sinks = sinks_.Items(); 149 sinks = sinks_.Items();
223 sinks_.Clear(); 150 sinks_.Clear();
224 webaudio_source_ = NULL;
225 capturer_ = NULL;
226 } 151 }
227 152
228 for (SinkList::ItemList::const_iterator it = sinks.begin(); 153 for (SinkList::ItemList::const_iterator it = sinks.begin();
229 it != sinks.end(); 154 it != sinks.end();
230 ++it){ 155 ++it){
231 (*it)->OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateEnded); 156 (*it)->OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateEnded);
232 (*it)->Reset(); 157 (*it)->Reset();
233 } 158 }
234 } 159 }
235 160
236 webrtc::AudioTrackInterface* WebRtcLocalAudioTrack::GetAudioAdapter() { 161 webrtc::AudioTrackInterface* WebRtcLocalAudioTrack::GetAudioAdapter() {
237 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 162 DCHECK(main_render_thread_checker_.CalledOnValidThread());
238 return adapter_.get(); 163 return adapter_.get();
239 } 164 }
240 165
241 } // namespace content 166 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698