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

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

Issue 671793004: Clean up the media stream audio track code (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 2 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 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/renderer/media/webrtc_audio_device_impl.h" 5 #include "content/renderer/media/webrtc_audio_device_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
9 #include "base/strings/string_util.h" 9 #include "base/strings/string_util.h"
10 #include "base/win/windows_version.h" 10 #include "base/win/windows_version.h"
11 #include "content/renderer/media/media_stream_audio_processor.h" 11 #include "content/renderer/media/media_stream_audio_processor.h"
12 #include "content/renderer/media/webrtc_audio_capturer.h" 12 #include "content/renderer/media/webrtc_audio_capturer.h"
13 #include "content/renderer/media/webrtc_audio_renderer.h" 13 #include "content/renderer/media/webrtc_audio_renderer.h"
14 #include "content/renderer/render_thread_impl.h" 14 #include "content/renderer/render_thread_impl.h"
15 #include "media/audio/audio_parameters.h" 15 #include "media/audio/audio_parameters.h"
16 #include "media/audio/sample_rates.h" 16 #include "media/audio/sample_rates.h"
17 17
18 using media::AudioParameters; 18 using media::AudioParameters;
19 using media::ChannelLayout; 19 using media::ChannelLayout;
20 20
21 namespace content { 21 namespace content {
22 22
23 WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl() 23 WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()
24 : ref_count_(0), 24 : ref_count_(0),
25 audio_transport_callback_(NULL), 25 audio_transport_callback_(NULL),
26 input_delay_ms_(0),
27 output_delay_ms_(0), 26 output_delay_ms_(0),
28 initialized_(false), 27 initialized_(false),
29 playing_(false), 28 playing_(false),
30 recording_(false), 29 recording_(false),
31 microphone_volume_(0), 30 microphone_volume_(0) {
32 is_audio_track_processing_enabled_(
33 MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled()) {
34 DVLOG(1) << "WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()"; 31 DVLOG(1) << "WebRtcAudioDeviceImpl::WebRtcAudioDeviceImpl()";
35 } 32 }
36 33
37 WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl() { 34 WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl() {
38 DVLOG(1) << "WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl()"; 35 DVLOG(1) << "WebRtcAudioDeviceImpl::~WebRtcAudioDeviceImpl()";
39 DCHECK(thread_checker_.CalledOnValidThread()); 36 DCHECK(thread_checker_.CalledOnValidThread());
40 Terminate(); 37 Terminate();
41 } 38 }
42 39
43 int32_t WebRtcAudioDeviceImpl::AddRef() { 40 int32_t WebRtcAudioDeviceImpl::AddRef() {
44 DCHECK(thread_checker_.CalledOnValidThread()); 41 DCHECK(thread_checker_.CalledOnValidThread());
45 return base::subtle::Barrier_AtomicIncrement(&ref_count_, 1); 42 return base::subtle::Barrier_AtomicIncrement(&ref_count_, 1);
46 } 43 }
47 44
48 int32_t WebRtcAudioDeviceImpl::Release() { 45 int32_t WebRtcAudioDeviceImpl::Release() {
49 DCHECK(thread_checker_.CalledOnValidThread()); 46 DCHECK(thread_checker_.CalledOnValidThread());
50 int ret = base::subtle::Barrier_AtomicIncrement(&ref_count_, -1); 47 int ret = base::subtle::Barrier_AtomicIncrement(&ref_count_, -1);
51 if (ret == 0) { 48 if (ret == 0) {
52 delete this; 49 delete this;
53 } 50 }
54 return ret; 51 return ret;
55 } 52 }
56 int WebRtcAudioDeviceImpl::OnData(const int16* audio_data,
57 int sample_rate,
58 int number_of_channels,
59 int number_of_frames,
60 const std::vector<int>& channels,
61 int audio_delay_milliseconds,
62 int current_volume,
63 bool need_audio_processing,
64 bool key_pressed) {
65 int total_delay_ms = 0;
66 {
67 base::AutoLock auto_lock(lock_);
68 // Return immediately when not recording or |channels| is empty.
69 // See crbug.com/274017: renderer crash dereferencing invalid channels[0].
70 if (!recording_ || channels.empty())
71 return 0;
72
73 // Store the reported audio delay locally.
74 input_delay_ms_ = audio_delay_milliseconds;
75 total_delay_ms = input_delay_ms_ + output_delay_ms_;
76 DVLOG(2) << "total delay: " << input_delay_ms_ + output_delay_ms_;
77 }
78
79 // Write audio frames in blocks of 10 milliseconds to the registered
80 // webrtc::AudioTransport sink. Keep writing until our internal byte
81 // buffer is empty.
82 const int16* audio_buffer = audio_data;
83 const int frames_per_10_ms = (sample_rate / 100);
84 CHECK_EQ(number_of_frames % frames_per_10_ms, 0);
85 int accumulated_audio_frames = 0;
86 uint32_t new_volume = 0;
87
88 // The lock here is to protect a race in the resampler inside webrtc when
89 // there are more than one input stream calling OnData(), which can happen
90 // when the users setup two getUserMedia, one for the microphone, another
91 // for WebAudio. Currently we don't have a better way to fix it except for
92 // adding a lock here to sequence the call.
93 // TODO(xians): Remove this workaround after we move the
94 // webrtc::AudioProcessing module to Chrome. See http://crbug/264611 for
95 // details.
96 base::AutoLock auto_lock(capture_callback_lock_);
97 while (accumulated_audio_frames < number_of_frames) {
98 // Deliver 10ms of recorded 16-bit linear PCM audio.
99 int new_mic_level = audio_transport_callback_->OnDataAvailable(
100 &channels[0],
101 channels.size(),
102 audio_buffer,
103 sample_rate,
104 number_of_channels,
105 frames_per_10_ms,
106 total_delay_ms,
107 current_volume,
108 key_pressed,
109 need_audio_processing);
110
111 accumulated_audio_frames += frames_per_10_ms;
112 audio_buffer += frames_per_10_ms * number_of_channels;
113
114 // The latest non-zero new microphone level will be returned.
115 if (new_mic_level)
116 new_volume = new_mic_level;
117 }
118
119 return new_volume;
120 }
121
122 void WebRtcAudioDeviceImpl::OnSetFormat(
123 const media::AudioParameters& params) {
124 DVLOG(1) << "WebRtcAudioDeviceImpl::OnSetFormat()";
125 }
126 53
127 void WebRtcAudioDeviceImpl::RenderData(media::AudioBus* audio_bus, 54 void WebRtcAudioDeviceImpl::RenderData(media::AudioBus* audio_bus,
128 int sample_rate, 55 int sample_rate,
129 int audio_delay_milliseconds, 56 int audio_delay_milliseconds,
130 base::TimeDelta* current_time) { 57 base::TimeDelta* current_time) {
131 render_buffer_.resize(audio_bus->frames() * audio_bus->channels()); 58 render_buffer_.resize(audio_bus->frames() * audio_bus->channels());
132 59
133 { 60 {
134 base::AutoLock auto_lock(lock_); 61 base::AutoLock auto_lock(lock_);
135 DCHECK(audio_transport_callback_); 62 DCHECK(audio_transport_callback_);
136 // Store the reported audio delay locally. 63 // Store the reported audio delay locally.
137 output_delay_ms_ = audio_delay_milliseconds; 64 output_delay_ms_ = audio_delay_milliseconds;
138 } 65 }
139 66
140 int frames_per_10_ms = (sample_rate / 100); 67 int frames_per_10_ms = (sample_rate / 100);
141 int bytes_per_sample = sizeof(render_buffer_[0]); 68 int bytes_per_sample = sizeof(render_buffer_[0]);
142 const int bytes_per_10_ms = 69 const int bytes_per_10_ms =
143 audio_bus->channels() * frames_per_10_ms * bytes_per_sample; 70 audio_bus->channels() * frames_per_10_ms * bytes_per_sample;
144 DCHECK_EQ(audio_bus->frames() % frames_per_10_ms, 0); 71 DCHECK_EQ(audio_bus->frames() % frames_per_10_ms, 0);
145 72
146 // Get audio frames in blocks of 10 milliseconds from the registered 73 // Get audio frames in blocks of 10 milliseconds from the registered
147 // webrtc::AudioTransport source. Keep reading until our internal buffer 74 // webrtc::AudioTransport source. Keep reading until our internal buffer
148 // is full. 75 // is full.
149 uint32_t num_audio_frames = 0;
150 int accumulated_audio_frames = 0; 76 int accumulated_audio_frames = 0;
151 int16* audio_data = &render_buffer_[0]; 77 int16* audio_data = &render_buffer_[0];
152 while (accumulated_audio_frames < audio_bus->frames()) { 78 while (accumulated_audio_frames < audio_bus->frames()) {
153 // Get 10ms and append output to temporary byte buffer. 79 // Get 10ms and append output to temporary byte buffer.
154 int64_t elapsed_time_ms = -1; 80 int64_t elapsed_time_ms = -1;
155 int64_t ntp_time_ms = -1; 81 int64_t ntp_time_ms = -1;
156 if (is_audio_track_processing_enabled_) { 82 static const int kBitsPerByte = 8;
157 // When audio processing is enabled in the audio track, we use 83 audio_transport_callback_->PullRenderData(bytes_per_sample * kBitsPerByte,
158 // PullRenderData() instead of NeedMorePlayData() to avoid passing the 84 sample_rate,
159 // render data to the APM in WebRTC as reference signal for echo 85 audio_bus->channels(),
160 // cancellation. 86 frames_per_10_ms,
161 static const int kBitsPerByte = 8; 87 audio_data,
162 audio_transport_callback_->PullRenderData(bytes_per_sample * kBitsPerByte, 88 &elapsed_time_ms,
163 sample_rate, 89 &ntp_time_ms);
164 audio_bus->channels(), 90 accumulated_audio_frames += frames_per_10_ms;
165 frames_per_10_ms,
166 audio_data,
167 &elapsed_time_ms,
168 &ntp_time_ms);
169 accumulated_audio_frames += frames_per_10_ms;
170 } else {
171 // TODO(xians): Remove the following code after the APM in WebRTC is
172 // deprecated.
173 audio_transport_callback_->NeedMorePlayData(frames_per_10_ms,
174 bytes_per_sample,
175 audio_bus->channels(),
176 sample_rate,
177 audio_data,
178 num_audio_frames,
179 &elapsed_time_ms,
180 &ntp_time_ms);
181 accumulated_audio_frames += num_audio_frames;
182 }
183 if (elapsed_time_ms >= 0) { 91 if (elapsed_time_ms >= 0) {
184 *current_time = base::TimeDelta::FromMilliseconds(elapsed_time_ms); 92 *current_time = base::TimeDelta::FromMilliseconds(elapsed_time_ms);
185 } 93 }
186 audio_data += bytes_per_10_ms; 94 audio_data += bytes_per_10_ms;
187 } 95 }
188 96
189 // De-interleave each channel and convert to 32-bit floating-point 97 // De-interleave each channel and convert to 32-bit floating-point
190 // with nominal range -1.0 -> +1.0 to match the callback format. 98 // with nominal range -1.0 -> +1.0 to match the callback format.
191 audio_bus->FromInterleaved(&render_buffer_[0], 99 audio_bus->FromInterleaved(&render_buffer_[0],
192 audio_bus->frames(), 100 audio_bus->frames(),
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 return 0; 326 return 0;
419 } 327 }
420 328
421 int32_t WebRtcAudioDeviceImpl::PlayoutDelay(uint16_t* delay_ms) const { 329 int32_t WebRtcAudioDeviceImpl::PlayoutDelay(uint16_t* delay_ms) const {
422 base::AutoLock auto_lock(lock_); 330 base::AutoLock auto_lock(lock_);
423 *delay_ms = static_cast<uint16_t>(output_delay_ms_); 331 *delay_ms = static_cast<uint16_t>(output_delay_ms_);
424 return 0; 332 return 0;
425 } 333 }
426 334
427 int32_t WebRtcAudioDeviceImpl::RecordingDelay(uint16_t* delay_ms) const { 335 int32_t WebRtcAudioDeviceImpl::RecordingDelay(uint16_t* delay_ms) const {
428 base::AutoLock auto_lock(lock_); 336 // There is no way to report a correct delay value to WebRTC since there
429 *delay_ms = static_cast<uint16_t>(input_delay_ms_); 337 // might be multiple WebRtcAudioCapturer instances.
430 return 0; 338 NOTREACHED();
339 return -1;
431 } 340 }
432 341
433 int32_t WebRtcAudioDeviceImpl::RecordingSampleRate( 342 int32_t WebRtcAudioDeviceImpl::RecordingSampleRate(
434 uint32_t* sample_rate) const { 343 uint32_t* sample_rate) const {
435 // We use the default capturer as the recording sample rate. 344 // We use the default capturer as the recording sample rate.
436 scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer()); 345 scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer());
437 if (!capturer.get()) 346 if (!capturer.get())
438 return -1; 347 return -1;
439 348
440 *sample_rate = static_cast<uint32_t>( 349 *sample_rate = static_cast<uint32_t>(
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 // If there is no capturer or there are more than one open capture devices, 429 // If there is no capturer or there are more than one open capture devices,
521 // return false. 430 // return false.
522 if (capturers_.empty() || capturers_.size() > 1) 431 if (capturers_.empty() || capturers_.size() > 1)
523 return false; 432 return false;
524 433
525 return GetDefaultCapturer()->GetPairedOutputParameters( 434 return GetDefaultCapturer()->GetPairedOutputParameters(
526 session_id, output_sample_rate, output_frames_per_buffer); 435 session_id, output_sample_rate, output_frames_per_buffer);
527 } 436 }
528 437
529 } // namespace content 438 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698