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

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: REBASE Created 4 years, 9 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 "content/public/renderer/media_stream_audio_sink.h" 11 #include "content/public/renderer/media_stream_audio_sink.h"
12 #include "content/renderer/media/media_stream_audio_level_calculator.h" 12 #include "content/renderer/media/media_stream_audio_level_calculator.h"
13 #include "content/renderer/media/media_stream_audio_processor.h" 13 #include "content/renderer/media/media_stream_audio_processor.h"
14 #include "content/renderer/media/media_stream_audio_sink_owner.h" 14 #include "content/renderer/media/media_stream_audio_sink_owner.h"
15 #include "content/renderer/media/media_stream_audio_track_sink.h" 15 #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" 16 #include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
18 #include "content/renderer/media/webrtc_audio_capturer.h"
19 17
20 namespace content { 18 namespace content {
21 19
22 WebRtcLocalAudioTrack::WebRtcLocalAudioTrack( 20 WebRtcLocalAudioTrack::WebRtcLocalAudioTrack(
23 WebRtcLocalAudioTrackAdapter* adapter, 21 scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter)
24 const scoped_refptr<WebRtcAudioCapturer>& capturer, 22 : MediaStreamAudioTrack(true), adapter_(std::move(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(); 23 signal_thread_checker_.DetachFromThread();
24 DVLOG(1) << "WebRtcLocalAudioTrack::WebRtcLocalAudioTrack()";
32 25
33 adapter_->Initialize(this); 26 adapter_->Initialize(this);
34
35 DVLOG(1) << "WebRtcLocalAudioTrack::WebRtcLocalAudioTrack()";
36 } 27 }
37 28
38 WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() { 29 WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() {
39 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 30 DCHECK(main_render_thread_checker_.CalledOnValidThread());
40 DVLOG(1) << "WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack()"; 31 DVLOG(1) << "WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack()";
41 // Users might not call Stop() on the track. 32 // Ensure the track is stopped.
42 Stop(); 33 MediaStreamAudioTrack::Stop();
43 } 34 }
44 35
45 media::AudioParameters WebRtcLocalAudioTrack::GetOutputFormat() const { 36 media::AudioParameters WebRtcLocalAudioTrack::GetOutputFormat() const {
46 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 37 DCHECK(main_render_thread_checker_.CalledOnValidThread());
47 if (webaudio_source_.get()) { 38 base::AutoLock auto_lock(lock_);
48 return media::AudioParameters(); 39 return audio_parameters_;
49 } else {
50 return capturer_->GetOutputFormat();
51 }
52 } 40 }
53 41
54 void WebRtcLocalAudioTrack::Capture(const media::AudioBus& audio_bus, 42 void WebRtcLocalAudioTrack::Capture(const media::AudioBus& audio_bus,
55 base::TimeTicks estimated_capture_time, 43 base::TimeTicks estimated_capture_time) {
56 bool force_report_nonzero_energy) {
57 DCHECK(capture_thread_checker_.CalledOnValidThread()); 44 DCHECK(capture_thread_checker_.CalledOnValidThread());
58 DCHECK(!estimated_capture_time.is_null()); 45 DCHECK(!estimated_capture_time.is_null());
59 46
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; 47 SinkList::ItemList sinks;
78 SinkList::ItemList sinks_to_notify_format; 48 SinkList::ItemList sinks_to_notify_format;
79 { 49 {
80 base::AutoLock auto_lock(lock_); 50 base::AutoLock auto_lock(lock_);
81 capturer = capturer_;
82 sinks = sinks_.Items(); 51 sinks = sinks_.Items();
83 sinks_.RetrieveAndClearTags(&sinks_to_notify_format); 52 sinks_.RetrieveAndClearTags(&sinks_to_notify_format);
84 } 53 }
85 54
86 // Notify the tracks on when the format changes. This will do nothing if 55 // Notify the tracks on when the format changes. This will do nothing if
87 // |sinks_to_notify_format| is empty. 56 // |sinks_to_notify_format| is empty. Note that accessing |audio_parameters_|
57 // without holding the |lock_| is valid since |audio_parameters_| is only
58 // changed on the current thread.
88 for (const auto& sink : sinks_to_notify_format) 59 for (const auto& sink : sinks_to_notify_format)
89 sink->OnSetFormat(audio_parameters_); 60 sink->OnSetFormat(audio_parameters_);
90 61
91 // Feed the data to the sinks. 62 // Feed the data to the sinks.
92 // TODO(jiayl): we should not pass the real audio data down if the track is 63 // 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 64 // disabled. This is currently done so to feed input to WebRTC typing
94 // detection and should be changed when audio processing is moved from 65 // detection and should be changed when audio processing is moved from
95 // WebRTC to the track. 66 // WebRTC to the track.
96 for (const auto& sink : sinks) 67 for (const auto& sink : sinks)
97 sink->OnData(audio_bus, estimated_capture_time); 68 sink->OnData(audio_bus, estimated_capture_time);
98 } 69 }
99 70
100 void WebRtcLocalAudioTrack::OnSetFormat( 71 void WebRtcLocalAudioTrack::OnSetFormat(
101 const media::AudioParameters& params) { 72 const media::AudioParameters& params) {
102 DVLOG(1) << "WebRtcLocalAudioTrack::OnSetFormat()"; 73 DVLOG(1) << "WebRtcLocalAudioTrack::OnSetFormat()";
103 // If the source is restarted, we might have changed to another capture 74 // If the source is restarted, we might have changed to another capture
104 // thread. 75 // thread.
105 capture_thread_checker_.DetachFromThread(); 76 capture_thread_checker_.DetachFromThread();
106 DCHECK(capture_thread_checker_.CalledOnValidThread()); 77 DCHECK(capture_thread_checker_.CalledOnValidThread());
107 78
79 base::AutoLock auto_lock(lock_);
108 audio_parameters_ = params; 80 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. 81 // Remember to notify all sinks of the new format.
113 sinks_.TagAll(); 82 sinks_.TagAll();
114 } 83 }
115 84
85 void WebRtcLocalAudioTrack::SetLevel(
86 scoped_refptr<MediaStreamAudioLevelCalculator::Level> level) {
87 adapter_->SetLevel(std::move(level));
88 }
89
116 void WebRtcLocalAudioTrack::SetAudioProcessor( 90 void WebRtcLocalAudioTrack::SetAudioProcessor(
117 const scoped_refptr<MediaStreamAudioProcessor>& processor) { 91 scoped_refptr<MediaStreamAudioProcessor> processor) {
118 // if the |processor| does not have audio processing, which can happen if 92 adapter_->SetAudioProcessor(std::move(processor));
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 } 93 }
125 94
126 void WebRtcLocalAudioTrack::AddSink(MediaStreamAudioSink* sink) { 95 void WebRtcLocalAudioTrack::AddSink(MediaStreamAudioSink* sink) {
127 // This method is called from webrtc, on the signaling thread, when the local 96 // 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 97 // description is set and from the main thread from WebMediaPlayerMS::load
129 // (via WebRtcLocalAudioRenderer::Start). 98 // (via WebRtcLocalAudioRenderer::Start).
130 DCHECK(main_render_thread_checker_.CalledOnValidThread() || 99 DCHECK(main_render_thread_checker_.CalledOnValidThread() ||
131 signal_thread_checker_.CalledOnValidThread()); 100 signal_thread_checker_.CalledOnValidThread());
132 DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()"; 101 DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()";
133 base::AutoLock auto_lock(lock_); 102 base::AutoLock auto_lock(lock_);
(...skipping 25 matching lines...) Expand all
159 MediaStreamAudioTrackSink::WrapsMediaStreamSink(sink)); 128 MediaStreamAudioTrackSink::WrapsMediaStreamSink(sink));
160 } 129 }
161 130
162 // Clear the delegate to ensure that no more capture callbacks will 131 // 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 132 // be sent to this sink. Also avoids a possible crash which can happen
164 // if this method is called while capturing is active. 133 // if this method is called while capturing is active.
165 if (removed_item.get()) 134 if (removed_item.get())
166 removed_item->Reset(); 135 removed_item->Reset();
167 } 136 }
168 137
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) { 138 void WebRtcLocalAudioTrack::SetEnabled(bool enabled) {
194 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 139 DCHECK(main_render_thread_checker_.CalledOnValidThread());
195 if (adapter_.get()) 140 if (adapter_.get())
196 adapter_->set_enabled(enabled); 141 adapter_->set_enabled(enabled);
197 } 142 }
198 143
199 void WebRtcLocalAudioTrack::Stop() { 144 void WebRtcLocalAudioTrack::OnStop() {
200 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 145 DCHECK(main_render_thread_checker_.CalledOnValidThread());
201 DVLOG(1) << "WebRtcLocalAudioTrack::Stop()"; 146 DVLOG(1) << "WebRtcLocalAudioTrack::OnStop()";
202 if (!capturer_.get() && !webaudio_source_.get())
203 return;
204 147
205 if (webaudio_source_.get()) { 148 // 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; 149 SinkList::ItemList sinks;
220 { 150 {
221 base::AutoLock auto_lock(lock_); 151 base::AutoLock auto_lock(lock_);
222 sinks = sinks_.Items(); 152 sinks = sinks_.Items();
223 sinks_.Clear(); 153 sinks_.Clear();
224 webaudio_source_ = NULL;
225 capturer_ = NULL;
226 } 154 }
227 155
228 for (SinkList::ItemList::const_iterator it = sinks.begin(); 156 for (SinkList::ItemList::const_iterator it = sinks.begin();
229 it != sinks.end(); 157 it != sinks.end();
230 ++it){ 158 ++it){
231 (*it)->OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateEnded); 159 (*it)->OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateEnded);
232 (*it)->Reset(); 160 (*it)->Reset();
233 } 161 }
234 } 162 }
235 163
236 webrtc::AudioTrackInterface* WebRtcLocalAudioTrack::GetAudioAdapter() { 164 webrtc::AudioTrackInterface* WebRtcLocalAudioTrack::GetAudioAdapter() {
237 DCHECK(main_render_thread_checker_.CalledOnValidThread()); 165 DCHECK(main_render_thread_checker_.CalledOnValidThread());
238 return adapter_.get(); 166 return adapter_.get();
239 } 167 }
240 168
241 } // namespace content 169 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/webrtc_local_audio_track.h ('k') | content/renderer/media/webrtc_local_audio_track_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698